多執行緒-衝突與同步程式碼
阿新 • • 發佈:2018-11-19
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) { 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();
}
}
注意:該程式碼並未完全解決問題。