转载请注明出处:blog.csdn.net/linglongxin…java
同步问题:如何保证同一资源被多个线程并发访问时的完整性。经常使用的同步方法是采用标记或加锁机制api
wait() / nofity() 方法是基类Object的两个方法,也就意味着全部Java类都会拥有这两个方法,这样,咱们就能够为任何对象实现同步机制。并发
wait()方法:当缓冲区已满/空时,生产者/消费者线程中止本身的执行,放弃锁,使本身处于等等状态,让其余线程执行。ide
notify()方法:当生产者/消费者向缓冲区放入/取出一个产品时,向其余等待的线程发出可执行的通知,同时放弃锁,使本身处于等待状态。测试
/** * Created by yuandl on 2016-10-11./** * 资源 */
public class Resource {
/*资源序号*/
private int number = 0;
/*资源标记*/
private boolean flag = false;
/** * 生产资源 */
public synchronized void create() {
if (flag) {//先判断标记是否已经生产了,若是已经生产,等待消费;
try {
wait();//让生产线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;//生产一个
System.out.println(Thread.currentThread().getName() + "生产者------------" + number);
flag = true;//将资源标记为已经生产
notify();//唤醒在等待操做资源的线程(队列)
}
/** * 消费资源 */
public synchronized void destroy() {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "消费者****" + number);
flag = false;
notify();
}
}复制代码
/** * Created by yuandl on 2016-10-11. * /** * 生产者 */
public class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.create();
}
}
}复制代码
/** * 消费者 */
public class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.destroy();
}
}
}复制代码
/** * Created by yuandl on 2016-10-11. */
public class ProducerConsumerTest {
public static void main(String args[]) {
Resource resource = new Resource();
new Thread(new Producer(resource)).start();//生产者线程
new Thread(new Consumer(resource)).start();//消费者线程
}
}复制代码
Thread-0生产者------------1
Thread-1消费者****1
Thread-0生产者------------2
Thread-1消费者****2
Thread-0生产者------------3
Thread-1消费者****3
Thread-0生产者------------4
Thread-1消费者****4
Thread-0生产者------------5
Thread-1消费者****5
Thread-0生产者------------6
Thread-1消费者****6
Thread-0生产者------------7
Thread-1消费者****7
Thread-0生产者------------8
Thread-1消费者****8
Thread-0生产者------------9
Thread-1消费者****9
Thread-0生产者------------10
Thread-1消费者****10复制代码
以上打印结果能够看出没有任何问题this
/** * Created by yuandl on 2016-10-11. */
public class ProducerConsumerTest {
public static void main(String args[]) {
Resource resource = new Resource();
new Thread(new Consumer(resource)).start();//生产者线程
new Thread(new Consumer(resource)).start();//生产者线程
new Thread(new Producer(resource)).start();//消费者线程
new Thread(new Producer(resource)).start();//消费者线程
}
}复制代码
Thread-0生产者------------100
Thread-3消费者****100
Thread-0生产者------------101
Thread-3消费者****101
Thread-2消费者****101
Thread-1生产者------------102
Thread-3消费者****102
Thread-0生产者------------103
Thread-2消费者****103
Thread-1生产者------------104
Thread-3消费者****104
Thread-1生产者------------105
Thread-0生产者------------106
Thread-2消费者****106
Thread-1生产者------------107
Thread-3消费者****107
Thread-0生产者------------108
Thread-2消费者****108
Thread-0生产者------------109
Thread-2消费者****109
Thread-1生产者------------110
Thread-3消费者****110复制代码
缘由分析spa
/** * Created by yuandl on 2016-10-11./** * 资源 */
public class Resource {
/*资源序号*/
private int number = 0;
/*资源标记*/
private boolean flag = false;
/** * 生产资源 */
public synchronized void create() {
while (flag) {//先判断标记是否已经生产了,若是已经生产,等待消费;
try {
wait();//让生产线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;//生产一个
System.out.println(Thread.currentThread().getName() + "生产者------------" + number);
flag = true;//将资源标记为已经生产
notify();//唤醒在等待操做资源的线程(队列)
}
/** * 消费资源 */
public synchronized void destroy() {
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "消费者****" + number);
flag = false;
notify();
}
}复制代码
再次发现问题 .net
缘由分析线程
解决方案code
/** * Created by yuandl on 2016-10-11./** * 资源 */
public class Resource {
/*资源序号*/
private int number = 0;
/*资源标记*/
private boolean flag = false;
/** * 生产资源 */
public synchronized void create() {
while (flag) {//先判断标记是否已经生产了,若是已经生产,等待消费;
try {
wait();//让生产线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;//生产一个
System.out.println(Thread.currentThread().getName() + "生产者------------" + number);
flag = true;//将资源标记为已经生产
notifyAll();//唤醒在等待操做资源的线程(队列)
}
/** * 消费资源 */
public synchronized void destroy() {
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "消费者****" + number);
flag = false;
notifyAll();
}
}复制代码
Thread-0生产者------------412
Thread-2消费者****412
Thread-0生产者------------413
Thread-3消费者****413
Thread-1生产者------------414
Thread-2消费者****414
Thread-1生产者------------415
Thread-2消费者****415
Thread-0生产者------------416
Thread-3消费者****416
Thread-1生产者------------417
Thread-3消费者****417
Thread-0生产者------------418
Thread-2消费者****418
Thread-0生产者------------419
Thread-3消费者****419
Thread-1生产者------------420
Thread-2消费者****420复制代码
以上就大功告成了,没有任何问题