Yod*_*oda 4 java multithreading notify
我有一个Java问题.我想编写一个程序,其中有Class Main,它有一些类的ThreadList(Class Task),它只写一个字母和数字.Object Main只是从ArrayList中唤醒一个Thread,让它在同一个对象(Main)睡眠另一个时执行某些操作.
它工作正常:0A,0B,0C,1B,1C,1A,2B,2A,2C,3B,3C,3A,4B,4C,4A,5B,5A,5C,
但只有当我评论:e.printStackTrace()e是Exception然后我在Main.run的java.lang.Object.notify(Native Method)中获得了很多java.lang.IllegalMonitorStateException(Main.java:22)
所以通知工作错误,我应该如何正确唤醒它,请告诉我,显示,正确.请
import java.util.ArrayList;
import java.util.ArrayList;
public class Main extends Thread {
ArrayList<Thread> threads;
public Main() {
super();
threads = new ArrayList<Thread>();
}
public void run() {
for (int i = 0; i < 3; i++) {
threads.add(new Thread(new Task(i + 65)));
}
long cT = System.currentTimeMillis();
for (int i = 0; i < threads.size(); i++) {
threads.get(i).start();
}
while (System.currentTimeMillis() - cT < 10000) {
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).notify();
// HOW TO WAKE THREAD FROM threads ArrayList
Thread.sleep(1000);
// how to put to bed the same thread ?
threads.get(i).wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new Main().start();
//new Thread(new Task(65)).start();
}
}
Run Code Online (Sandbox Code Playgroud)
H
public class Task implements Runnable {
int nr;
char character;
public Task(int literaASCII) {
this.nr = 0;
character = (char) (literaASCII);
}
@Override
public void run() {
while (true) {
try {
System.out.print(nr + "" + character + ", ");
nr++;
int r = (int) ((Math.random() * 500) + 500); // <500ms,1000ms)
Thread.sleep(r);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Run Code Online (Sandbox Code Playgroud)
rod*_*ion 12
sleep而且wait非常不同.sleep只是暂停当前线程达到指定的时间,并且没有与其他线程直接交互.
wait更复杂:想法wait是暂停一个给定监视器上的线程(或锁定,如果你愿意)并让其他线程工作,直到它notify在该监视器上并释放它.因此wait,notify涉及两个或多个线程之间的交互.
因为这种相互作用的,为了使wait和notify正确地工作,这就要求这些方法必须拥有监视器(锁定),这意味着,该线程object.wait()或object.notify()必须从内部被称为synchronized(object){ ... }块.如果你打电话object.wait()没有synchronized-block,你将永远得到一个IllegalMonitorStateException.
在你的代码中,
for (int i = 0; i < threads.size(); i++) {
threads.get(i).start();
}
Run Code Online (Sandbox Code Playgroud)
这将启动所有线程,然后将同时运行所有线程,而不是一次一个地运行它们.
要确保一次只运行一个线程,您需要将一个公共监视器对象传递给所有线程并将它们wait放在该监视器上.例如:
public class Main extends Thread {
//...
public void run(){
//Initialize all threads with common monitor object
Object monitor = new Object();
for (int i = 0; i < 3; i++) {
threads.add(new Thread(new Task(i + 65, monitor)));
}
long cT = System.currentTimeMillis();
for (int i = 0; i < threads.size(); i++) {
//All threads will start, and immediately pause on monitor.wait()
threads.get(i).start();
}
synchronized(monitor){
while (System.currentTimeMillis() - cT < 10000) {
//All threads are currently waiting, so we need to wake one random
//thread up by calling notify on monitor. Other thread will not run yet,
//because this thread still holds the monitor.
monitor.notify();
//Make this thread wait, which will temporarily release the monitor
//and let the notified thread run.
monitor.wait();
}
}
}
}
//...
public class Task implements Runnable{
int nr;
char character;
Object monitor;
public Task(int literaASCII, Object monitor) {
this.nr = 0;
this.monitor = monitor;
character = (char) (literaASCII);
}
@Override
public void run() {
synchronized(monitor){
while (true) {
//Pause this thread and let some other random thread
//do the work. When other thread finishes and calls notify()
//this thread will continue (if this thread is picked).
monitor.wait();
try {
System.out.print(nr + "" + character + ", ");
nr++;
int r = (int) ((Math.random() * 500) + 500); // <500ms,1000ms)
Thread.sleep(r);
} catch (Exception e) {
e.printStackTrace();
}
//This thread has finished work for now.
//Let one other random thread know.
monitor.notify();
//Other thread will not be able to do work until this thread
//releases the monitor by calling monitor.wait() or
//completely exists the synchronized(monitor){ ... } block.
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它的行为可能与您的初衷略有不同,因为线程会随机唤醒,因此无法保证输出将按任何特定顺序排列.
还要注意的是,一般你应该更喜欢notifyAll()到notify(),除非你有一个很好的理由来使用notify().因为notify()只唤醒一个线程,如果该线程"忘记"最后调用notify,所有其他线程可能wait永远.
| 归档时间: |
|
| 查看次数: |
46646 次 |
| 最近记录: |