多线程模式
代码:
//临界区模式 public class Main { public static void main(String[] args) { TicketEntrance ticketEntrance = new TicketEntrance(); new PassengerThread(ticketEntrance,"A","A-DEST").start(); new PassengerThread(ticketEntrance,"B","B-DEST").start(); new PassengerThread(ticketEntrance,"C","C-DEST").start(); } } public class PassengerThread extends Thread { //旅客要通过的检票口 private final TicketEntrance ticketEntrance; //姓名 private final String name; //目的地 private final String dest; public PassengerThread(TicketEntrance ticketEntrance, String name, String dest) { this.ticketEntrance = ticketEntrance; this.name = name; this.dest = dest; } @Override public void run() { while (true){ ticketEntrance.pass(name,dest); } } } public class TicketEntrance { private int no = 0; private String passengerName = "nobody"; private String passengerDest = "nowhere"; public synchronized void pass(String name, String dest) { this.no++; this.passengerName = name; this.passengerDest = dest; check(); } @Override public String toString() { return "TicketEntrance{" + "no=" + no + ", passengerName='" + passengerName + '\'' + ", passengerDest='" + passengerDest + '\'' + '}'; } private void check() { if (passengerName.charAt(0) != passengerDest.charAt(0)) { System.out.println("****错误****" + toString()); } } public synchronized void setPassengerDest(String passengerDest) { this.passengerDest = passengerDest; } public synchronized void setPassengerName(String passengerName) { this.passengerName = passengerName; } }
//imutable public class Main { public static void main(String[] args) { Person person = new Person("lucy", 12313, "male"); ShowPersonThread showPersonThread = new ShowPersonThread(person); ShowPersonThread showPersonThread2 = new ShowPersonThread(person); ShowPersonThread showPersonThread3 = new ShowPersonThread(person); showPersonThread.start(); showPersonThread2.start(); showPersonThread3.start(); } }
public class Person {
private String name;
private int id;
private String sex;
public Person(String name, int id, String sex) {
this.name = name;
this.id = id;
this.sex = sex;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", id=" + id +
", sex='" + sex + '\'' +
'}';
}
}
public class ShowPersonThread extends Thread{
Person person;
public ShowPersonThread(Person person) {
this.person = person;
}
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+"---"+person);
}
}
}
//guardedsuspension01
public class Courier extends Thread { private final Random random; private final RequestConllection requestConllection; public Courier(RequestConllection requestConllection, String name, long seed) { super(name); this.requestConllection=requestConllection; this.random=new Random(seed); } @Override public void run() { for (int i = 0; i < 10000; i++) { Request request = new Request("请求编号: " + i); try { requestConllection.putRequest(request); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"发出请求"+request); try { Thread.sleep(random.nextInt(1000)); } catch (InterruptedException e) { } } } } public class Main { public static void main(String[] args) { RequestConllection requestConllection = new RequestConllection(); new Courier(requestConllection,"京东快递员",3141592L).start(); new Mother(requestConllection,"王大妈",1231332L).start(); new Mother(requestConllection,"周大妈",1231335L).start(); } } public class Mother extends Thread{ private final Random random; private final RequestConllection requestConllection; public Mother(RequestConllection requestConllection, String name, long seed) { super(name); this.random = new Random(seed); this.requestConllection = requestConllection; } @Override public void run() { for (int i = 0; i < 10000; i++) { Request request = null; try { request = requestConllection.getRequest(); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 处理请求 "+request); try { Thread.sleep(random.nextInt(1000)); } catch (InterruptedException e) { } } } } public class Request { String name; public Request(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Request{" + "name='" + name + '\'' + '}'; } } public class RequestConllection { private final Queue<Request> queue = new LinkedList<Request>(); public synchronized Request getRequest() { while (queue.peek()==null){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } return queue.remove(); } public synchronized void putRequest(Request request) throws InterruptedException { queue.offer(request); notifyAll(); } }
//guardedsuspension02 public class Courier extends Thread { private final Random random; private final RequestConllection requestConllection; public Courier(RequestConllection requestConllection, String name, long seed) { super(name); this.requestConllection=requestConllection; this.random=new Random(seed); } @Override public void run() { for (int i = 0; i < 10000; i++) { Request request = new Request("请求编号: " + i); try { requestConllection.putRequest(request); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"发出请求"+request); try { Thread.sleep(random.nextInt(1000)); } catch (InterruptedException e) { } } } }
public class Main {
public static void main(String[] args) {
RequestConllection requestConllection = new RequestConllection();
new Courier(requestConllection,"京东快递员",3141592L).start();
new Mother(requestConllection,"王大妈",1231332L).start();
new Mother(requestConllection,"周大妈",1231335L).start();
}
}
public class Mother extends Thread{
private final Random random;
private final RequestConllection requestConllection;
public Mother(RequestConllection requestConllection,String name, long seed) {
super(name);
this.random = new Random(seed);
this.requestConllection = requestConllection;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
Request request = null;
try {
request = requestConllection.getRequest();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 处理请求 "+request);
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
public class Request {
String name;
public Request(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Request{" +
"name='" + name + '\'' +
'}';
}
}
public class RequestConllection {
private final BlockingQueue<Request> queue = new LinkedBlockingQueue<Request>();
public Request getRequest() throws InterruptedException {
return queue.take();
}
public void putRequest(Request request) throws InterruptedException {
queue.put(request);
}
}
//balking
public class Customer { private String name; private boolean girlNeedWater; public Customer(String name) { this.name = name; this.girlNeedWater=false; } public synchronized void girlNeedWater(){ girlNeedWater=true; } public synchronized void pourWater(){ if (!girlNeedWater) { return; } doPourWater(); girlNeedWater=false; } public void doPourWater(){ System.out.println(Thread.currentThread().getName()+" 倒水 "); } } public class GirlFriend extends Thread { private String name; private final Customer boyFriend; private final Random random = new Random(); public GirlFriend(Customer boyFriend, String name) { super(name); this.boyFriend = boyFriend; } @Override public void run() { try { while (true) { boyFriend.girlNeedWater(); Thread.sleep(random.nextInt(1000)); boyFriend.pourWater(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class Main { public static void main(String[] args) { Customer customer = new Customer("you"); new GirlFriend(customer,"GirlFriend").start(); new Waiter(customer,"Waiter").start(); } } public class Waiter extends Thread { private String name; private final Customer customer; public Waiter(Customer customer,String name) { super(name); this.customer=customer; } @Override public void run() { try { while (true){ customer.pourWater(); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
//producerconsumer
public class DelayedQueneTest { public static void main(String[] args) throws InterruptedException { Item item1 = new Item("item1", 5, TimeUnit.SECONDS); Item item2 = new Item("item2",10, TimeUnit.SECONDS); Item item3 = new Item("item3",15, TimeUnit.SECONDS); DelayQueue<Item> queue = new DelayQueue<>(); queue.put(item1); queue.put(item2); queue.put(item3); System.out.println("begin time:" + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); for (int i = 0; i < 3; i++) { Item take = queue.take(); System.out.format("name:{%s}, time:{%s}\n",take.name, LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)); } } } class Item implements Delayed { /* 触发时间*/ private long time; String name; public Item(String name, long time, TimeUnit unit) { this.name = name; this.time = System.currentTimeMillis() + (time > 0? unit.toMillis(time): 0); } @Override public long getDelay(TimeUnit unit) { return time - System.currentTimeMillis(); } @Override public int compareTo(Delayed o) { Item item = (Item) o; long diff = this.time - item.time; if (diff <= 0) {// 改成>=会造成问题 return -1; }else { return 1; } } @Override public String toString() { return "Item{" + "time=" + time + ", name='" + name + '\'' + '}'; } }
//readwritelock
public class Data { private final char[] buffer; private final ReadWriteLock lock = new ReadWriteLock(); public Data(int size) { this.buffer = new char[size]; for (int i = 0; i < buffer.length; i++) { buffer[i] = '*'; } } public char[] read() throws InterruptedException { lock.readLock(); try { return doRead(); } finally { lock.readUnlock(); } } public void write(char c) throws InterruptedException{ lock.writeLock(); try { doWrite(c); } finally { lock.writeUnlock(); } } private char[] doRead() { char[] newbuf = new char[buffer.length]; for (int i = 0; i < buffer.length; i++) { newbuf[i]=buffer[i]; } rest(10); return newbuf; } private void doWrite(char c){ for (int i = 0; i < buffer.length; i++) { buffer[i]=c; rest(30); } } private void rest(int seconds){ try { Thread.sleep(seconds); } catch (InterruptedException e) { } } } public class Main { public static void main(String[] args) { Data data = new Data(10); for (int i = 0; i < 6; i++) { new ReaderThread(data).start(); } new WriterThread(data,"ABCDEFG").start(); new WriterThread(data,"abcdefg").start(); } } public class ReaderThread extends Thread{ private final Data data; public ReaderThread(Data data) { this.data = data; } @Override public void run() { try { while (true){ char[] readbuf=data.read(); System.out.println(getName()+"读取"+String.valueOf(readbuf)); } } catch (InterruptedException e) { } } } public class ReadWriteLock { private int readingReaders = 0; //实际正在读取中的线程个数 private int waitingWriters = 0; //正在等待写入的线程个数 private int writingWrites = 0; //实际正在写入中的线程个数 private boolean preferWriter = true; //若写入优先,则为true /** * 使用了guardedsuspension模式 * * @throws InterruptedException */ public synchronized void readLock() throws InterruptedException { while (writingWrites > 0 || (preferWriter && waitingWriters > 0)) { wait(); } readingReaders++; } public synchronized void readUnlock() { readingReaders--; preferWriter = true; notifyAll(); } public synchronized void writeLock() throws InterruptedException { try { waitingWriters++; while (readingReaders > 0 || writingWrites > 0) { wait(); } } finally { waitingWriters--; } writingWrites++; } public synchronized void writeUnlock() { writingWrites--; preferWriter = false; notifyAll(); } } public class WriterThread extends Thread { private static final Random random=new Random(); private final Data data; private final String filter; private int index=0; public WriterThread(Data data, String filter) { this.data = data; this.filter = filter; } @Override public void run() { try { while (true){ char c=nextchar(); data.write(c); System.out.println(Thread.currentThread().getName()+"写入"+String.valueOf(c)); } } catch (InterruptedException e) { } } private char nextchar() { char c = filter.charAt(index); index++; if (index>=filter.length()) { index=0; } return c; } } 1、该模式使用了GuardedSuspension模式 读锁的守护条件是没有其他线程写入或者等待写入 写锁的守护条件是没有其他线程写入或者读取 2、适合读多写少的场景 3、请注意这里的读锁和写锁是逻辑锁,不是物理锁 思考:在数据类中,为何将加锁的函数调用放在try/finally之外? 如果将其放在try/finally之内,当线程被interrupt中断的时候,可能会出现过多调用unlock方法的情况; preferWriter字段的作用: 1、如果读线程比写线程多,一个读线程获取锁释放后,又被另一个读线程拿到,写线程就可能很少有机会执行; 2、如果写线程比读线程多,那么也有可能导致读很少有机会执行; 3、注意preferWriter属性的变化,在readUnlock的时候,会将其修改为true,在writeUnlock的时候,会修改 为false,这样的话,就能避免上述两种情况的出现; 如果写线程比读线程多:那么preferWriter为false,则读线程有机会执行。
//perReuquest 委托者 public class BoyFriend { public static void main(String[] args) { System.out.println("BoyFriend 开始发出请求"); GirlFriend girlFriend = new GirlFriend(); girlFriend.request("收下快递"); girlFriend.request("收下衣服"); girlFriend.request("买瓶酒"); girlFriend.request("BoyFriend终止发出请求"); } } public class GirlFriend { public void request(final String request){ System.out.println("请求"+request+"开始"); new Thread(){ @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("女朋友执行"+request); } }.start(); System.out.println("请求"+request+"结束"); } }
public class CookThread extends Thread{ private final Kitchen kitchen; public CookThread(String name,Kitchen kitchen) { super(name); this.kitchen=kitchen; } @Override public void run() { while (true){ Request request = kitchen.cook(); request.execute(); } } } public class CustomerThread extends Thread { private final Kitchen kitchen; private static final Random random=new Random(); public CustomerThread(String name,Kitchen kitchen) { super(name); this.kitchen = kitchen; } @Override public void run() { try { for (int i = 0; true; i++) { Request request = new Request(getName(), i); kitchen.order(request); Thread.sleep(random.nextInt(1000)); } } catch (InterruptedException e) { } } } public class Kitchen { public static final int MAX_REQUEST=100; private final Request[] requestQueue; private int tail;//下次putRequest的数量 private int head;//下次takeReuqest的数量 private int count;//Request的数量 private final CookThread[] cookThreads; public Kitchen(int cookCount) { this.requestQueue=new Request[MAX_REQUEST]; this.head=0; this.tail=0; this.count=0; cookThreads = new CookThread[cookCount]; for (int i = 0; i < cookThreads.length; i++) { cookThreads[i] = new CookThread("cook-"+i,this); } } public void startCookers(){ for (int i = 0; i < cookThreads.length; i++) { cookThreads[i].start(); } } public synchronized void order(Request request){ while (count>=requestQueue.length){ try { wait(); } catch (InterruptedException e) { } } requestQueue[tail]=request; tail=(tail+1)%requestQueue.length; count++; notifyAll(); } public synchronized Request cook(){ while (count<=0){ try { wait(); } catch (InterruptedException e) { } } Request request=requestQueue[head]; head=(head+1)%requestQueue.length; count--; notifyAll(); return request; } } public class Main { public static void main(String[] args) { Kitchen kitchen = new Kitchen(5); kitchen.startCookers(); new CustomerThread("小李",kitchen).start(); new CustomerThread("小王",kitchen).start(); new CustomerThread("小张",kitchen).start(); } } public class Request { private final String name; private final int number; private static final Random random = new Random(); public Request(String name, int number) { this.name=name; this.number=number; } public void execute(){ System.out.println(Thread.currentThread().getName()+"做菜"+this); try { Thread.sleep(random.nextInt(1000)); } catch (InterruptedException e) { } } @Override public String toString() { return "Request{" + "name='" + name + '\'' + ", number=" + number + '}'; } }