集美大学 计算机 郑如滨

教学博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1. 使用synchronized(互斥)解决代码冲突问题

public class TestSynchronizedThread {

	/**
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub

		Thread t1 = new Thread(new Adder());
		Thread t2 = new Thread(new Adder());
		Thread t3 = new Thread(new Adder());

		Thread t4 = new Thread(new Subtracter());
		Thread t5 = new Thread(new Subtracter());
		Thread t6 = new Thread(new Subtracter());

		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		t6.start();

		t1.join();
		t2.join();
		t3.join();
		t4.join();
		t5.join();
		t6.join();

		System.out.println(Counter.getId());
		System.out.println("main end");
	}
}

class Adder implements Runnable {

	@Override
	public void  run() {
		for (int i = 0; i < 10000; i++)
			Counter.addId();
		System.out.println(Thread.currentThread().getName() + " end");
	}
}

class Subtracter implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 10000; i++)
			Counter.subtractId();
		System.out.println(Thread.currentThread().getName() + " end");
	}
}

class Counter {
	private static int id = 0;

	public static  void addId() {
		synchronized (Counter.class) { //同步代码块。获得指定对象的内在锁。这里是获得Counter.class这个对象的内在锁。效率更高(仅必要的代码块进入同步)
			id++;
		}
		
	}

	public static synchronized void subtractId() { //静态同步方法。获得当前对象(Counter.class)的内在锁。
		id--;
	}

	public static int getId() {
		return id;
	}
}

2. 使用synchronized、wait、notify解决线程间的合作(同步)问题

主程序代码
1个生产者与3个消费者,同时运行,产生了线程的同步问题。

public class MyProducerConsumerTestUpdate {

	/**
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		Repository repo = new Repository();
		Thread producer = new Thread(new Producer(repo,1500));
		Thread consumer1 = new Thread(new Consumer(repo,500));
		Thread consumer2 = new Thread(new Consumer(repo,500));
		Thread consumer3 = new Thread(new Consumer(repo,500));
		producer.start();
		consumer1.start();
		consumer2.start();
		consumer3.start();
		producer.join();
		consumer1.join();
		consumer2.join();
		consumer3.join();
		
		System.out.println("main end! repo中还有 "+repo.size()+"个货物!");
	}

}

生产者与消费者代码

class Consumer implements Runnable {
	private Repository repo;
	private int count;//让Consumer取count次

	public Consumer(Repository repo, int count) {
		this.repo = repo;
		this.count = count;
	}

	@Override
	public void run() {
		for (int i = 0; i < count; i++) {
			repo.get();//每回都从仓库中取出一个货物
		}
		System.out.format("取出%d个货物完毕!",count);

	}

}
class Producer implements Runnable {

	private Repository repo;
	private int count; //让Producer放入count次

	public Producer(Repository repo, int count) {
		this.repo = repo;
		this.count = count;
	}

	@Override
	public void run() {
		for (int i = 0; i < count; i++) {
			repo.put(new String("sth"));// 每回都放入一个新的货物(字符串对象)
		}
		System.out.format("放入%d个货物完毕!",count);
		
	}

}

仓库代码(重点)注意其中的wait、notify的时机

import java.util.ArrayList;
import java.util.List;

class Repository {// 存放字符串的仓库
	private int capacity = 10;//仓库容量默认为10
	private List<String> repo = new ArrayList<>();// repo(仓库),最多只能放10个

	public synchronized void put(String t) { //同步代码首先要使用synchronized以实现互斥访问。
		try {
			if (size() == capacity){ //同步问题中,应当将对条件的判断放入循环中,以保证条件确实满足。
				System.out.println("仓库已满,请稍等");
				wait();
			}
			repo.add(t);
			System.out.println("放了一件货物到repo");
			notifyAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public synchronized void get() {
		try {
			if (size() == 0) {  //这里不能解决问题。同步问题中,应当将对条件的判断放入循环中,以保证条件确实满足。
				System.out.println("仓库中无货物,请稍候");
				wait();
			} 
			repo.remove(0);
			System.out.println("从repo取出一件货物");
			notifyAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public int getCapacity(){ //返回仓库容量
		return capacity;
	}
	public synchronized int size(){ //思考:该方法是否应该使用synchronized修饰
		return repo.size();
	}
}

注意:该代码并未同步解决问题。思考:如果一个生产者一下唤醒多个消费者,或者相反,会出现什么情况?

posted on 2018-11-19 12:58  zhrb  阅读(382)  评论(0编辑  收藏  举报