您的位置:首页 > 编程语言 > Java开发

java线程同步与通信

2016-08-02 20:00 483 查看
一、java线程同步:同一时间只能有一个线程访问共享资源。

1、原理:每个Java对象中都有一个监视程序,同一时间只有一个线程持有该监视程序。

2、同步的弊端:同步会让整个程序执行缓慢。

3、实现同步的方式:

1)同步方法:使用synchronized修饰需要同步的方法,同步整个方法,实现线程排队执行,用法参考代码:

public class SynchronizeMethodDemo implements Runnable {
private static int money = 0;// 模拟共享资源
public static void main(String[] args) {
SynchronizeMethodDemo sm = new SynchronizeMethodDemo();
Thread t1 = new Thread(sm, "线程A");
Thread t2 = new Thread(sm, "线程B");
t1.start();
t2.start();
}
@Override
<span style="color:#FF0000;">public synchronized void run</span>() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("当前线程:" + Thread.currentThread().getName()
+ ":" + money++);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
当前线程:线程B:0
当前线程:线程B:1
当前线程:线程A:2
当前线程:线程A:3特殊情况:当2个线程使用的不是同一个对象,则这2个线程不能实现同步,代码如下:
public class SynchronizeMethodDemo implements Runnable {
private static int money = 0;// 模拟共享资源
public static void main(String[] args) {
//sm和sm1不是同一个对象,各自有自己的监视程序,所以不能同步
SynchronizeMethodDemo sm = new SynchronizeMethodDemo();
SynchronizeMethodDemo sm1 = new SynchronizeMethodDemo();
Thread t1 = new Thread(sm, "线程A");
Thread t2 = new Thread(sm1, "线程B");
t1.start();
t2.start();
}
@Override
public synchronized void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("当前线程:" + Thread.currentThread().getName()
+ ":" + money++);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}运行结果:
当前线程:线程B:0
当前线程:线程A:1
当前线程:线程B:2
当前线程:线程A:3
2)同步语句块:使用synchronized修饰需要同步的代码,只同步方法里面的部分代码,使用参考代码(包含2种写法):

public class SynchronizeStatement implements Runnable {
private static int money = 0;// 模拟共享资源
<span style="color:#FF0000;">private Object obj=new Object();</span>
public static void main(String[] args) {
SynchronizeStatement sm = new SynchronizeStatement();
Thread t1 = new Thread(sm, "线程A");
Thread t2 = new Thread(sm, "线程B");
t1.start();
t2.start();
}
@Override
public void run() {
<span style="color:#FF0000;">synchronized (this)</span> {
for (int i = 0; i < 2; i++) {
System.out.println("同步语句块1:" + Thread.currentThread().getName()
+ ":" + money++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
<span style="color:#FF0000;">synchronized (obj)</span> {
for (int i = 0; i < 2; i++) {
System.out.println("同步语句块2:" + Thread.currentThread().getName()
+ ":" + money++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}二、实现线程间的通信
1、线程间通信使用的方法:

1)wait()方法:告知当前线程放弃对监视程序的控制并等待直至另一线程调用notify()方法。

2)notify()方法:唤醒正在等待被执行对象的监视程序的线程。如果多个线程正在等待中,将随机选择其中一个线程。

3)notifyAll()方法:唤醒正在等待对象的监视程序的所有线程。

2、使用参考代码:

class Synchronize {
int d;
boolean flag = false;// 表示是否已生产产品
//消费商品
synchronized int getData() {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Get Data:" + d);
flag = false;
notify();//通知生产者,生产新的商品
return d;
}
// 生产商品
synchronized void putData(int d) {
// 如果已经生产产品,等待
if (flag) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.d = d;
flag = true;//通知消费者消费商品
System.out.println("put Data:" + d);
notify();
}
}
// 生产者线程
class Producer extends Thread {
Synchronize t;
public Producer(Synchronize t) {
this.t = t;
}
public void run() {
int data = 700;
while (true) {
System.out.println("put");
t.putData(data++);
}
}
}
class Consumer extends Thread {
Synchronize t;
public Consumer(Synchronize t) {
this.t = t;
}
public void run() {
while (true) {
System.out.println("get");
t.getData();
}
}
}
public class ProducerConsumer {
public static void main(String[] args) {
Synchronize obj = new Synchronize();
Producer t1 = new Producer(obj);
Consumer t2 = new Consumer(obj);
t1.start();
t2.start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: