如何在静态同步块内进行线程间通信

时间:2017-04-27 15:43:08

标签: java multithreading synchronized

我有一个关于静态同步方法和类级别锁定的问题。 有人可以帮我解释这个例子:

class Test
{
    synchronized static void printTest(int n)
    {
        for (int i = 1; i <= 10; i++) {
            System.out.println(n * i);
            try {
                Thread.sleep(400);
            } catch (Exception ignored) {}
        }
    } 
}  

class MyThread1 extends Thread
{
    public void run()
    {
        Test.printTest(1);
    }
}

class MyThread2 extends Thread
{
    public void run()
    {
        Test.printTest(10);
    }
}

public class TestSynchronization
{
    public static void main(String[] args)
    {
        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
        t1.start();
        t2.start();
    }
}

问题:

当线程t1处于循环中间(printTest()内)时,我想让它停止执行并将控制转移到线程t2。 有没有办法做到这一点?

由于我们处理类级锁定,我相信我们不能在这里使用对象级别wait()notify()方法来释放对象级锁定。但是在类级别锁定的情况下,如何释放它并将控件提供给其他一些等待的线程?

我们如何通知第二个线程在执行过程中等待线程1持有的类级锁定?

3 个答案:

答案 0 :(得分:1)

interrupt()可以在这里用于您的要求。

如果您的需求将来发生变化,并且在第二个线程之后需要执行第一个线程,则删除if(Thread.interrupted())内的printTest

 class Test {
    synchronized static void printTest(int n) {
        for (int i = 1; i <= 10; i++) {
            if(Thread.interrupted())
                break;
            System.out.println(n * i);
            try {
                Thread.sleep(400);
            } catch (Exception e) {
            }
        }
    }
 }

 class MyThread1 extends Thread {
    public void run() {
        Test.printTest(1);
    }
 }

 class MyThread2 extends Thread {
    public void run() {
        Test.printTest(10);
    }
 }

 public class TestSynchronization {
    public static void main(String t[]) throws InterruptedException {
        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
        t1.start();
        t2.start();

        t1.interrupt();
        t1.join();
    }

 }

答案 1 :(得分:1)

  

由于我们处理类级别锁定,我认为我们无法使用对象级别wait()notify()

我尽量避免说“班级”或“对象级别”。无论何时使用synchronized,您都在同步某个对象。请记住:Test.class 对象:它是包含描述Test类的所有运行时信息的对象。

当你说“类级锁定”时,你真正在谈论的是在全局单例对象(类对象)上进行同步,而不是“实例级锁定”该类的许多不同实例可以独立synchronized

  

我想让它停止执行并将控制转移到线程t2。

这不是考虑线程的非常有用的方法。您通常不希望程序中的某个线程等待轮到其执行某项任务:您希望它等待自己的任务。线程总是需要某些来协调和相互沟通,但是你能够让每个线程做更多的事情,你会更好地利用它们。

您不希望将“转移控制”从一个线程转移到另一个线程,而是希望每个线程始终控制自己的事物。

  

我们如何通知正在等待锁定的第二个线程?

nothing 可以释放线程等待进入synchronized块。这是synchronized的限制之一,这也是为什么任何线程永远停留在synchronized块中比更新几个字段更长的一个原因之一。< / p>

  

我想让它停止执行

引起循环线程注意的最简单方法是让线程每次循环检查volatile boolean变量的值。

volatile boolean timeToStop = false;

MyType myMethod(...) {
    while (! timeToStop) {
        ...
    }
}

然后,任何其他线程都可以设置timeToStop=true;以获得第一个线程的注意。

答案 2 :(得分:0)

来自你的评论:

  

有一个线程(t2)在另一个线程(t1)持有的类级锁上等待。因此,t1线程可以在t1退出静态同步方法之前通知线程t2。

是的,类是对象,只需调用notify()

class Test
{

   synchronized static void printTest( int n )
   {
      for( int i = 1; i <= 10; i++ ) {
         System.out.println( n * i );
      }
      try {
        Test.class.notify();     // just use a class literal
      } catch( Exception ignored ) {
      }

   }
}