无法通知锁定
我已经对java线程编码进行了测试,但是我有一些基本问题。经过几个小时的尝试和搜索,我决定尝试一下!无法通知锁定
我不明白为什么我的等待仍然锁定即使我的通知:
在这里你可以找到我的代码:
public class Mymain {
public static void main(String[] args) {
for(int i=0;i<100;i++){
new ThreadClass(i).start();
}
}
}
public class ThreadClass extends Thread {
static boolean ok = false;
int id;
public ThreadClass(int i) {
id = i;
}
public void run() {
System.out.println("Thread start " + id);
Last.toDo(id);
if (id == 5)
try {
waiting();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (id != 5)
awaking();
System.out.println("thread end " + id);
}
private synchronized void awaking() {
// TODO Auto-generated method stub
if (ok) {
System.out.println("i'm " + id + " and i'm Awaking 5");
ok = false;
notify();
System.out.println("I did the notify and i'm " + id);
}
}
private synchronized void waiting() throws InterruptedException {
System.out.println("Sleeping");
ok = true;
wait();
System.out.println("Awake 5");
}
}
然后开始循环,或者去在死锁不能确定..它应该只是停止与ID = 5的线程,然后下一个线程应重新启动ID = 5 ..但线程5从未醒来后通知...
在结果中,你可以看到我有2个线程试图唤醒线程5和螺纹5的自启动^^
看我做你的代码的一些变化:
- 你不能只是
notify()
,你会通知this
。你不能只是wait()
,你会永远等下去。你必须在Object上使用这些函数,所以我添加了一个Integer
对象(只是为了向你展示 - 你必须选择正确的对象)。
- 你哟和
static synchronized
之间的了解。快速搜索会导致你一个完美的答案。
- 为什么功能
waiting()
被同步?只有线程号码5调用它。
- 当调用一个
Object.notify()
/Object.wait()
,必须声明在对象同步块。
下面是一些代码:
public class Threads {
public static void main(String[] args) {
Integer intObject = new Integer(0);
for(int i=0;i<100;i++){
new ThreadClass(i, intObject).start();
}
}
}
class ThreadClass extends Thread {
static boolean ok = false;
int id;
Integer intObject;
public ThreadClass(int i, Integer intObject) {
id = i;
this.intObject = intObject;
}
public void run() {
System.out.println("Thread start " + id);
//Last.toDo(id);
if (id == 5)
waiting();
else
awaking(this);
System.out.println("thread end " + id);
}
private static synchronized void awaking(ThreadClass t) {
if(ok) {
System.out.println("i'm " + t.id + " and i'm Awaking 5");
ok = false;
synchronized (t.intObject) {
t.intObject.notify();
}
System.out.println("I did the notify and i'm " + t.id);
}
}
private void waiting(){
System.out.println("Sleeping");
ok = true;
synchronized (intObject) {
try {
intObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Awake 5");
}
}
的问题是,你不打电话通知()对同一对象总是要等着那你打电话给wait()。特别是,线程5本身正在调用wait(),但例如,线程8正在调用notify()而不是线程5.结果,线程5从未收到通知。
此外,您需要使ok
变量volatile
确保当一个线程设置它时,其他线程可以看到更改。这不会在这种特殊情况下造成问题,但在其他情况下可能会导致问题。
我不明白为什么我的等待仍然锁定即使我的通知:
等待并使用同一个对象实例时通知工作。如果你具有例如:
String x1 = "...";
String x2 = "...";
和线#1的作用:
synchronized (x1) { x1.wait(); }
和线#2,那么做:
synchronized (x2) { x2.wait(); }
那么线程#1仍然会等待,因为通知仅限于x2
。在您的示例中,由于您使用的是方法同步,因此ID为5的线程正在等待其自己的ThreadClass
实例。然后当其他线程调用awaking()
时,他们也调用了ThreadClass
的实例的通知。如果你想让线程#5看到另一个线程的通知,那么他们应该共享一个锁定对象。
也许是这样的:
final Object lock = new Object();
for (int id = 0; id < 100; id++){
new ThreadClass(id, lock).start();
}
...
public class ThreadClass extends Thread {
private final Object lock;
...
public ThreadClass(int id, Object lock) {
this.id = id;
this.lock = lock;
}
...
private void awaking() {
...
synchronized (lock) {
lock.notify();
}
...
}
private void waiting() throws InterruptedException {
...
synchronized (lock) {
lock.wait();
}
...
}
}
泰的回答很明确^^现在我知道了^^ – JustMe
为什么你不使用notifyAll的()方法?当你调用通知(),这意味着只有一个线程将状态从等待到可运行改变,但有可能是情况下,当你这是在排队等候以及多个线程和其他线程,他们将不会收到此通知。在我看来,最好使用notifyAll。
不要这么认为^^我解决了建议从其他成员^^ – JustMe
这篇文章没有准确回答这个问题。如果线程不使用相同的锁,则它们调用的方法无关紧要。 –
你能告诉我们你的输出是什么,它应该是什么? –
你可以把它放在你的问题中,以便格式化以便于分析吗? –
@WarrenDew完^^ – JustMe