java中线程同步问题

先不多说,直接上个例子,著名的生产者消费者问题。

 1 public class ProducerConsumer {
 2     public static void main(String[] args) {
 3         SyncStack ss = new SyncStack();
 4         Producer p = new Producer(ss);
 5         Consumer c = new Consumer(ss);
 6         new Thread(p).start();//生产者线程
 7         new Thread(c).start();//消费者线程
 8     }
 9 }
10 /**
11 消费的物品---窝头
12 **/
13 class WoTou {
14     int id;
15     WoTou(int id) {
16         this.id = id;
17     }
18     public String toString() {
19         return "WoTou : " + id;
20     }
21 }
22 /**
23 消费的空间---堆栈
24 **/
25 class SyncStack {
26     int index = 0;
27     WoTou[] arrWT = new WoTou[6];
28
29     public synchronized void push(WoTou wt) {
30         while(index == arrWT.length) {//是while而不是if的原因,当wait被打断的时候依旧要检查下堆栈是否满了
31             try {
32                 this.wait();
33             } catch (InterruptedException e) {
34                 e.printStackTrace();
35             }
36         }
37         this.notifyAll();
38         arrWT[index] = wt;
39         index ++;
40     }
41
42     public synchronized WoTou pop() {
43         while(index == 0) {
44             try {
45                 this.wait();
46             } catch (InterruptedException e) {
47                 e.printStackTrace();
48             }
49         }
50         this.notifyAll();
51         index--;
52         return arrWT[index];
53     }
54 }
55
56 /**
57 生产者类
58 **/
59 class Producer implements Runnable {
60     SyncStack ss = null;
61     Producer(SyncStack ss) {
62         this.ss = ss;
63     }
64
65     public void run() {
66         for(int i=0; i<20; i++) {
67             WoTou wt = new WoTou(i);
68             ss.push(wt);
69 System.out.println("生产了:" + wt);
70             try {
71                 Thread.sleep((int)(Math.random() * 200));
72             } catch (InterruptedException e) {
73                 e.printStackTrace();
74             }
75         }
76     }
77 }
78 /**
79 消费者类
80 **/
81 class Consumer implements Runnable {
82     SyncStack ss = null;
83     Consumer(SyncStack ss) {
84         this.ss = ss;
85     }
86
87     public void run() {
88         for(int i=0; i<20; i++) {
89             WoTou wt = ss.pop();
90 System.out.println("消费了: " + wt);
91             try {
92                 Thread.sleep((int)(Math.random() * 1000));
93             } catch (InterruptedException e) {
94                 e.printStackTrace();
95             }
96         }
97     }
98 }

效果如图:

synchronized的引入,学过数据库系统和操作系统的朋友应该会有所了解,对于共享资源,当一个线程占用的时候不能被其他线程操作,和操作系统的原子操作的原理有些相似。当synchronized之后,就会获得对象锁,其他线程就无法获得对象锁。

wait的引入:例如上题堆栈中只能放6个窝头,但是当堆栈中有6个窝头的时候,生产者获得对象锁的时候就不能生产了,因此,生产者就会进入wait池,同时又会释放对象锁。

notify的引入:唤醒wait池中的一个线程(ps:只能唤醒别的线程,不能唤醒自己)

notifyall的引入:唤醒wait池中的所有线程

在最后,给大家说下wait和sleep的区别吧,个人理解:

1.wait是Object类中方法,会抛出InteruptException,sleep是Thread类中的方法,wait方法只用在获得对象所得时候才能用,否则会抛异常;

2.wait方法会释放对象锁,但是sleep不会释放对象锁;

3.wait后的线程需要其他的线程去唤醒,但是sleep的线程在规定的时间后会自动唤醒。

时间: 2024-10-11 21:19:59

java中线程同步问题的相关文章

Java中线程同步的理解 - 其实应该叫做Java线程排队

Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程"同步"机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize(使同时发生)翻译过来的.我也不明白为什么

JAVA中线程同步的方法(7种)汇总

一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态. 注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类. 二.同步代码块 即有synchronized关键字修饰的语句块. 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步 代码如: synchronized(object){ } 注:同步是一种高开销

java中线程同步

最近用到线程同步,思路有点不是很清晰了,只记得synchronized和lock,其区别什么的记不清了.抽点空进行一下总结: lock接口 基本上拥有synchronized的所有功能 还提供了三种形式的锁获取(可中断.不可中断和定时)在其性能特征.排序保证或其他实现质量上可能会有所不同. 如线程A和B都要获取对象O的锁,A线程首先获取到了对象O的锁,那么B将要等待A释放对O的锁定 此时如果使用的是synchronized,若A不释放锁,B将会一直等下去,直到A释放对O的锁定 如果使用的是loc

JAVA中线程同步的方法

用什么关键字修饰同步方法 ? 用synchronized关键字修饰同步方法  同步有几种实现方法,都是什么?分别是synchronized,wait与notify wait():使一个线程处于等待状态,并且释放所持有的对象的lock.sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常.notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线

Java中线程的同步问题

在生活中我们时常会遇到同步的问题,而且大多数的实际问题都是线程的同步问题 我这里以生活中的火车售票来进行举例: 假设现在我们总共有1000张票要进行出售,共有10个出售点,那么当售票到最后只有一张票时,每个售票点如何去处理这唯一的一张票?或者对于某一张票而言,假设它正在售票站1售票的程序执行过程中,但是还没有出售,那么此时,其他售票站改如何去处理这张票呢? 这时,应该考虑使用java中的同步机制: 方法一:使用Runnable接口实现 package thread; public class T

Java中线程封闭之ThreadLocal

在访问共享数据时通常使用同步.若不使用同步则可以将对象封闭在一个线程中达到线程安全的目的,该方法称为线程封闭(Thread Confinement).其中实现线程封闭中规范的方法是使用ThreadLocal类.线程封闭技术一种常用的使用场景是在JDBC Connection对象. public class ConnectionHelper{private final static String URL = "";private final static ThreadLocal<C

Java 并发 线程同步

Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大多数实际的多线程应用中,两个或两个以上的线程需要共享对同一数据的存取,这将产生同步问题(可见性和同步性的丢失) 比如两个线程同时执行指令account[to] += amount,这不是原子操作,可能被处理如下: a)将account[to]加载到寄存器 b)增加amount c)将结果写回acco

java中线程存活和线程执行的问题!

1 /* 2 下面的程序会出现下面的情况,当Thread-0, Thread-1, Thread-2都被wait的时候,可能会同时苏醒 3 Thread-0 put 4 Thread-1 put 5 Thread-2 put 6 Thread-3 get//在此处,Thread-3拿到锁之后,将所有的等待的线程唤醒,才有了下面的输出 7 Thread-2 put 8 Thread-1 put 9 Thread-0 put 10 */ 11 12 13 虽然多个线程会同时苏醒,但是只有一个能获得c

Java多线程基础(四)Java传统线程同步通信技术

Java多线程基础(四)Java传统线程同步通信技术 编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声