在synchronized static方法中调用Class对象的wait()/notify()方法

原创
2020/03/20 13:53
阅读数 734

先贴一段在通常情况下使用wait()/notify()方法的示例demo

public class Test {

	public static void main(String[] args) {
		Object lock = new Object();// 锁对象
		
		// target线程,此线程将被挂起
		Thread target = new Thread(() -> waited(lock));
		target.start();

		// action线程,用此线程唤醒上述target线程
		Thread action = new Thread(() -> wakeUp(lock));
		action.start();
	}

	private static void waited(Object lock) {
		synchronized (lock) {
			int times = 0;
			try {
				while (true) {// 循环打印数字,直至线程被挂起
					System.out.println(times);
					times++;
					if (times == 5) {// 当循环到第五次时,挂起线程
						System.out.println("目标线程被挂起");
						lock.wait();
					}
					Thread.sleep(1000);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private static void wakeUp(Object lock) {
		try {
			Thread.sleep(10000);
			synchronized (lock) {
				lock.notify();
				System.out.println("唤醒目标线程");
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

几乎在所有的教程里,使用wait()/notify()方法时,都是要求程序员先new一个Object对象作为调用目标,在调用Object对象的wait()/notify()方法前要先给对象加锁。

设想了一下,如果线程调用的方法都是静态方法(整个业务逻辑里没有new任何对象),并且这些静态方法都在同一个class里面,那么直接给静态方法加上synchronized关键字(众所周知,直接在静态方法上添加synchronized关键字,实际上就是给静态方法所在的class文件加了锁),然后直接使用“类名.class”来调用Class对象wait()/notify(),按理说应该也是可以的。因为网上没有相关的测试代码,就自己写了一个测试了一下。

最后的结论是可以的。

贴一下代码

public class Test {

	public static void main(String[] args) {
		// target线程,此线程将被挂起
		Thread target = new Thread(() -> waited());
		target.start();

		// action线程,用此线程唤醒上述target线程
		Thread action = new Thread(() -> wakeUp());
		action.start();
	}

	private synchronized static void waited() {
		int times = 0;
		try {
			while (true) {// 循环打印数字,直至线程被挂起
				System.out.println(times);
				times++;
				if (times == 5) {// 当循环到第五次时,挂起线程
					System.out.println("目标线程被挂起");
					Test.class.wait();
				}
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private synchronized static void wakeUp() {
		try {
			Thread.sleep(10000);
			Test.class.notify();
			System.out.println("唤醒目标线程");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

两种写法的运行效果完全一致

其实在真实的业务逻辑中,几乎不可能出现整个项目中不new任何对象的情况,也很难保证所有的静态方法都在同一个class文件中。但不排除某些奇葩公司的奇葩面试题里会问到这个。

展开阅读全文
加载中
点击加入讨论🔥(2) 发布并加入讨论🔥
2 评论
0 收藏
0
分享
返回顶部
顶部