• 多线程-冲突与同步代码


    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() { //同步方法,获得当前对象的内在锁
    		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.remove();//每回都从仓库中取出一个货物
    		}
    		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.add(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<String>();// repo(仓库),最多只能放10个
    
    	public synchronized void add(String t) {
    		try {
    			if (size() == capacity){
    				System.out.println("仓库已满,请稍等");
    				wait();
    			}
    			repo.add(t);
    			System.out.println("放一件东西到repo");
    			notify();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    
    	public synchronized void remove() {
    		try {
    			if (size() == 0) {
    				System.out.println("仓库中无货物,请稍候");
    				wait();
    			} 
    			repo.remove(0);
    			System.out.println("从repo取出一件货物");
    			notify();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	public int getCapacity(){//返回仓库容量
    		return capacity;
    	}
    	public synchronized int size(){
    		return repo.size();
    	}
    }
    

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

  • 相关阅读:
    51nod 1163 最高的奖励
    51nod 1191 消灭兔子
    51nod 2538 二三排列
    node做渲染服务器的实现
    gulp静态服务器的搭建
    canvas中裁切(橡皮檫)的应用--探照灯,点击去除遮罩
    canvas中图片、视频的加载(截图、切片)
    canvas中笔触基础知识
    Gitee的使用流程
    gulp的使用
  • 原文地址:https://www.cnblogs.com/zhrb/p/9982543.html
Copyright © 2020-2023  润新知