java线程中的一些问题

(1)notifyAll无法唤醒的问题

一个线程处于wait状态,另一个线程无法唤醒它。主要原因不是共享变量的问题,只要共享变量为对象成员或静态变量即可。因为wait()和notifyAll必须属于同一实体,所以当调用了a.wait()后,必须调用a.notifyAll才能唤醒a线程。

(2)java.lang.IllegalMonitorStateException异常

这个异常与前一个问题有一定的关系,解决了上一个问题后,只要在wait和notify前面加上synchronized(Object)或在调用这两个方法的函数中加上synchronized即可解决。

(3)线程对象如果是一个类的成员,可能无法创建,原因是这个类的对象没有创建,或Thread对象被析构

如下面是一个线程类:

package test;

public class MyThread implements Runnable {

    public MyThread() {
    
    }

    public void run() {
        // TODO Auto-generated method stub
        while(true) {
            System.out.println("My Thread are runing");
            try {
                synchronized(this) {
                this.wait(1000);}
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

如果主类中加入一个该类的成员:

package test;

public class testThread {
	private static MyThread myThread;
	public testThread() {
		// TODO Auto-generated constructor stub
		myThread = new MyThread();
	}

	public static void main(String[] args) {

		Thread thread = new Thread(myThread);
		thread.start();
	}

}

则此时,这个线程无法运行。主要原因是该线程是testThread的成员,而main函数运行时,并没有创建testThread对象,所以myThread并没有被创建。

改为下面的代码即可运行:

package test;

public class testThread {
	private static MyThread myThread;
	public testThread() {
		// TODO Auto-generated constructor stub
		myThread = new MyThread();
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		testThread t = new testThread();
		Thread thread = new Thread(myThread);
		thread.start();
	}

}

  但是如下代码还是不能运行,不管myThread是不是静态成员

package test;

public class TestThread2 {
    private MyThread myThread;
    public TestThread2() {
        MyThread myThread = new MyThread();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestThread2 t = new TestThread2();
        t.runThread();
    }
    
    public void runThread() {
        Thread thread = new Thread(myThread);
        thread.start();
    }

}

但是如果将Thread变量也设置为成员,则可以运行

package test;

public class TestThread2 {
    private MyThread myThread;
    private Thread thread;
    public TestThread2() {
        MyThread myThread = new MyThread();
        thread = new Thread(myThread);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestThread2 t = new TestThread2();
        t.runThread();
    }
    
    public void runThread() {
        //Thread thread = new Thread(new MyThread());
        thread.start();
    }

}

总结,如果只将runnable作为成员,在创建时由于Thread 变量是临时变量,可能被析构,所以不能创建线程。但如果Thread与runnable都作为成员,则没有问题了。

原文地址:https://www.cnblogs.com/myboat/p/12986932.html