Java之线程(synchronized,wait(),notify(),notifyAll())

本文详细解析Java多线程中的核心概念与方法,包括synchronized关键字的不同应用场景、线程间通信机制如wait()和notify()的正确使用方式。通过实例演示如何实现线程间的同步与等待。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考资料
Java多线程入门大全(适用于有一定基础者)
[url]http://www.chinaitpower.com/A/2002-04-09/19260.html[/url]
Java多线程sleep(),join(),interrupt(),wait(),notify()
[url]http://www.blogjava.net/fhtdy2004/archive/2009/06/08/280728.html[/url]
JAVA多线程suspend()、resume()和wait()、notify()的区别
[url]http://luckyapple.iteye.com/blog/457298[/url]
[i]总结如下:[/i]
[b]1.有synchronized的地方不一定有wait,notify,notifyAll,
2.有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized.
3.如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是current thread了.
4 推荐使用notifyAll.[/b]
[color=red]一 synchronized的4种用法[/color]
1 方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.

public synchronized void synMethod() {
//方法体
}

2 对某一代码块使用synchronized后跟括号,括号里是变量,一次只有一个线程进入该代码块

public int synMethod(int a1){
synchronized(a1) {
//一次只能有一个线程进入
}
}

3 synchronized后面括号里是一对象,此时,线程获得的是对象锁

public class MyThread implements Runnable {

public static void main(String args[]) {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt, "t1");
Thread t2 = new Thread(mt, "t2");
t1.start();
t2.start();
}

public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
}
}
}

4 synchronized后面括号里是类,只要线程进入,则该类中所有操作不能进行,包括静态变量和静态方法,实际上,对于含有静态方法和静态变量的代码块的同步,我们通常用4来加锁

synchronized(A.class) {
//
}

示例如下:

public class MyRunnable implements Runnable {

@SuppressWarnings("deprecation")
@Override
public void run() {
System.out.println("咫尺天涯的第一个线程(Runnable)启动了。。。");
synchronized (this) {
System.out.println("开始执行任务了...");
//模仿一个任务所要的时间
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务完成了,我来叫醒你好吗?");
//推荐使用这种方式来唤醒线程上等待的对象
notifyAll();
}
}
}


public class Main {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
Thread runnable = new Thread(myRunnable,"咫尺天涯(Runnable)");
runnable.start();

synchronized (runnable) {

try {
System.out.println("快点完成任务呀,等待你来唤醒我。。。");
//当前线程A等待
runnable.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("你叫醒我了...");
}
}
}

输出结果如下:

快点完成任务呀,等待你来唤醒我。。。
咫尺天涯的第一个线程(Runnable)启动了。。。
开始执行任务了...
任务完成了,我来叫醒你好吗?
你叫醒我了...

网上有个示例不错,它是等待一个计算结果,如下:

/**
* 计算1+2+3 ... +100的和
*
* @author leizhimin 2008-9-15 13:20:49
*/
public class ThreadB extends Thread {
int total;

public void run() {
synchronized (this) {
for (int i = 0; i < 101; i++) {
total += i;
}
//(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒
notify();
}
}
}


/**
* 计算输出其他线程锁计算的数据
*
* @author leizhimin 2008-9-15 13:20:38
*/
public class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
//启动计算线程
b.start();
//线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者
synchronized (b) {
try {
System.out.println("等待对象b完成计算。。。");
//当前线程A等待
b.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b对象计算的总和是:" + b.total);
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值