1、Semaphore  信号量

Semaphore(信号量)是一个控制访问多个共享资源的计数器。

当一个线程想要访问某个共享资源,首先,它必须获得semaphore。如果semaphore的内部计数器的值大于0,那么semaphore减少计数器的值并允许访问共享的资源。计数器的值大于0表示,有可以自由使用的资源,所以线程可以访问并使用它们。

另一种情况,如果semaphore的计数器的值等于0,那么semaphore让线程进入休眠状态一直到计数器大于0。计数器的值等于0表示全部的共享资源都正被线程们使用,所以此线程想要访问就必须等到某个资源成为自由的。

当线程使用完共享资源时,他必须放出semaphore为了让其他线程可以访问共享资源。这个操作会增加semaphore的内部计数器的值。

例子1:

用Semaphore类来实现一种比较特殊的semaphores种类,称为binary semaphores。这个semaphores种类保护访问共享资源的独特性,所以semaphore的内部计数器的值只能是1或者0。

public class PrintQueue {private final Semaphore semaphore;public PrintQueue() {semaphore = new Semaphore(1);}public void printJob(Object document) {try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+": Going to print a job" );Thread.sleep((long) (new Random().nextInt(5))*1000);System.out.println(Thread.currentThread().getName()+": " + document);System.out.println(Thread.currentThread().getName()+": The document has been printed" );           } catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}}public static void main(String args[]) {PrintQueue printQueue = new PrintQueue();Thread thread[] = new Thread[10];for (int i = 0; i < 10; i++) {thread[i] = new Thread(new Job(printQueue), "Thread" + i);}for (int i = 0; i < 10; i++) {thread[i].start();}}
}class Job implements Runnable {private PrintQueue printQueue;public Job(PrintQueue printQueue) {this.printQueue = printQueue;}@Overridepublic void run() {printQueue.printJob(new Object());}
}

输出:

run:
Thread0: Going to print a job
Thread0: java.lang.Object@3485def8
Thread0: The document has been printed
Thread1: Going to print a job
Thread1: java.lang.Object@30c3bb57
Thread1: The document has been printed
Thread2: Going to print a job
Thread2: java.lang.Object@24065c4
Thread2: The document has been printed
Thread3: Going to print a job
Thread3: java.lang.Object@51d92803
Thread3: The document has been printed
Thread4: Going to print a job
Thread4: java.lang.Object@7d206f0
Thread4: The document has been printed
Thread5: Going to print a job
Thread5: java.lang.Object@6dc57a92
Thread5: The document has been printed
Thread6: Going to print a job
Thread6: java.lang.Object@3ff23f8b
Thread6: The document has been printed
Thread7: Going to print a job
Thread7: java.lang.Object@3929df79
Thread7: The document has been printed
Thread8: Going to print a job
Thread8: java.lang.Object@6c0e9e40
Thread8: The document has been printed
Thread9: Going to print a job
Thread9: java.lang.Object@33b7b32c
Thread9: The document has been printed
BUILD SUCCESSFUL (total time: 21 seconds)

Semaphore的构造参数sync设为1,此时semaphore.acquire()、semaphore.release() 与 synchronized 有相同效果。

其他备注:

1、Semaphore 的 acquireUninterruptibly() 方法忽略中断

2、Semaphore 的 tryAcquire() 方法,不能获得即返回

3、Semaphore 的参数fair默认非公平,若要公平可使用 Semaphore(int permits, boolean fair)

例子2:

semaphores也可以用来保护多个资源的副本,也就是说当你有一个代码片段每次可以被多个线程执行。

public class PrintQueue3 {private boolean freePrinters[];private Lock lockPrinters;private final Semaphore semaphore;public PrintQueue3() {semaphore = new Semaphore(3);freePrinters = new boolean[]{true, true, true};lockPrinters = new ReentrantLock();}public void printJob(Object document) {try {semaphore.acquire();int assignedPrinter = getPrinter();System.out.println(Thread.currentThread().getName() + ": Going to print a job");Thread.sleep((long) (new Random().nextInt(5)) * 1000);System.out.println(Thread.currentThread().getName() +  ": " +" -- " + assignedPrinter + " -- " +document);System.out.println(Thread.currentThread().getName() + ": The document has been printed");freePrinters[assignedPrinter] = true;} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}}private int getPrinter() {int ret = -1;try {lockPrinters.lock();for (int i = 0; i < freePrinters.length; i++) {if (freePrinters[i]) {ret = i;freePrinters[i] = false;break;}}} finally {lockPrinters.unlock();}return ret;}public static void main(String args[]) {PrintQueue3 printQueue3 = new PrintQueue3();Thread thread[] = new Thread[10];for (int i = 0; i < 10; i++) {thread[i] = new Thread(new Job3(printQueue3), "Thread" + i);}for (int i = 0; i < 10; i++) {thread[i].start();}}
}
class Job3 implements Runnable {private PrintQueue3 printQueue3;public Job3(PrintQueue3 printQueue3) {this.printQueue3 = printQueue3;}@Overridepublic void run() {printQueue3.printJob(new Object());}
}

打印:

Thread0: Going to print a job

Thread2: Going to print a job

Thread1: Going to print a job

Thread2:  -- 2 -- java.lang.Object@3929df79

Thread2: The document has been printed

Thread3: Going to print a job

Thread3:  -- 2 -- java.lang.Object@6c0e9e40

Thread3: The document has been printed

Thread7: Going to print a job

Thread1:  -- 1 -- java.lang.Object@33b7b32c

Thread1: The document has been printed

Thread8: Going to print a job

Thread8:  -- 1 -- java.lang.Object@6154283a

Thread8: The document has been printed

Thread4: Going to print a job

Thread7:  -- 2 -- java.lang.Object@5c1d29c1

Thread0:  -- 0 -- java.lang.Object@7ea06d25

Thread0: The document has been printed

Thread6: Going to print a job

Thread7: The document has been printed

Thread5: Going to print a job

Thread4:  -- 1 -- java.lang.Object@2b571dff

Thread6:  -- 0 -- java.lang.Object@64726693

Thread6: The document has been printed

Thread4: The document has been printed

Thread9: Going to print a job

Thread5:  -- 2 -- java.lang.Object@12ac706a

Thread5: The document has been printed

Thread9:  -- 0 -- java.lang.Object@770848b9

Thread9: The document has been printed

2、CountDownLatch  倒时计数闩

CountDownLatch 允许1个或者多个线程一直等待,直到一组操作执行完成。

CountDownLatch 初始一个整数值,此值是线程将要等待的操作数。

await():某个线程为了想要执行这些操作而等待时,让线程进入休眠直到操作完成。

countDown():当某个操作结束,减少CountDownLatch类的内部计数器。当计数器到达0时,这个类会唤醒全部使用await() 方法休眠的线程们。

await(long time, TimeUnit unit): 此方法会休眠直到被中断

public class CountDownLatchTest {public static void main(String[] args) {Videoconference conference = new Videoconference(10);Thread threadConference = new Thread(conference);threadConference.start();for (int i = 0; i < 10; i++) {Participant p = new Participant(conference, " Participant" + i);Thread t = new Thread(p);t.start();}}
}class Videoconference implements Runnable {private final CountDownLatch controller;public Videoconference(int number) {controller = new CountDownLatch(number);}public void arrive(String name) {System.out.println(name + "  has arrived");controller.countDown();System.out.println("Waiting for  " + controller.getCount() + "   participants. ");}@Overridepublic void run() {System.out.println("Initialization:" + controller.getCount() + " participants");try {controller.await();System.out.println("All   the participants have come");System.out.println(" Let 's start...");} catch (InterruptedException e) {e.printStackTrace();}}
}class Participant implements Runnable {private Videoconference conference;private String name;public Participant(Videoconference conference, String name) {this.conference = conference;this.name = name;}@Overridepublic void run() {long duration = (long) (Math.random() * 10);try {TimeUnit.SECONDS.sleep(duration);} catch (InterruptedException e) {e.printStackTrace();}conference.arrive(name);}
}

打印:

Initialization:10 participants
 Participant6  has arrived
Waiting for  9   participants. 
 Participant4  has arrived
Waiting for  8   participants. 
 Participant0  has arrived
Waiting for  7   participants. 
 Participant9  has arrived
Waiting for  6   participants. 
 Participant3  has arrived
Waiting for  5   participants. 
 Participant7  has arrived
Waiting for  4   participants. 
 Participant2  has arrived
Waiting for  3   participants. 
 Participant5  has arrived
Waiting for  2   participants. 
 Participant1  has arrived
 Participant8  has arrived
Waiting for  1   participants. 
Waiting for  0   participants. 
All   the participants have come
 Let 's start...

CountDownLatch类有3个基本元素:

  1. 初始值决定CountDownLatch类需要等待的事件的数量。
  2. await() 方法, 被等待全部事件终结的线程调用。
  3. countDown() 方法,事件在结束执行后调用

CountDownLatch 机制不是用来保护共享资源或者临界区。它是用来同步一个或者多个执行多个任务的线程。它只能使用一次。像之前解说的,一旦CountDownLatch的计数器到达0,任何对它的方法的调用都是无效的。如果你想再次同步,你必须创建新的对象。

3、CyclicBarrier  循环屏障

CyclicBarrier 类有一个整数初始值,此值表示将在同一点同步的线程数量。

当其中一个线程到达确定点,它会调用await() 方法来等待其他线程。当线程调用这个方法,CyclicBarrier阻塞线程进入休眠直到其他线程到达。

当最后一个线程调用CyclicBarrier 类的await() 方法,它唤醒所有等待的线程并继续执行它们的任务。

CyclicBarrier 类与CountDownLatch有一些共同点,但是也有一些不同。

最主要的不同是,CyclicBarrier对象可以重置到它的初始状态,重新分配新的值给内部计数器,即使它已经被初始过了。而CoiuntDownLatch不能重置。

public class CyclicBarrierTest {public static void main(String[] args) {final int ROWS = 10000;final int NUMBERS = 1000;final int SEARCH = 5;final int PARTICIPANTS = 5;final int LINES_PARTICIPANT = 2000;MatrixMock mock = new MatrixMock(ROWS, NUMBERS, SEARCH);Results results = new Results(ROWS);Grouper grouper = new Grouper(results);CyclicBarrier barrier = new CyclicBarrier(PARTICIPANTS, grouper);Searcher searchers[] = new Searcher[PARTICIPANTS];for (int i = 0; i < PARTICIPANTS; i++) {searchers[i] = new Searcher(i * LINES_PARTICIPANT, (i * LINES_PARTICIPANT) + LINES_PARTICIPANT, mock, results, 5, barrier);Thread thread = new Thread(searchers[i]);thread.start();}System.out.printf("Main: The main thread has finished.\n");}
}class MatrixMock {private int data[][];public MatrixMock(int size, int length, int number) {int counter = 0;data = new int[size][length];Random random = new Random();for (int i = 0; i < size; i++) {for (int j = 0; j < length; j++) {data[i][j] = random.nextInt(10);if (data[i][j] == number) {counter++;}}}System.out.printf("Mock: There are %d ocurrences of number in generated data.\n", counter, number); //译者注:把字符串里的number改为%d.}public int[] getRow(int row) {if ((row >= 0) && (row < data.length)) {return data[row];}return null;}
}class Results {private int data[];public Results(int size) {data = new int[size];}public void setData(int position, int value) {data[position] = value;}public int[] getData() {return data;}
}class Searcher implements Runnable {private int firstRow;private int lastRow;private MatrixMock mock;private Results results;private int number;private final CyclicBarrier barrier;public Searcher(int firstRow, int lastRow, MatrixMock mock, Results results, int number, CyclicBarrier barrier) {this.firstRow = firstRow;this.lastRow = lastRow;this.mock = mock;this.results = results;this.number = number;this.barrier = barrier;}@Overridepublic void run() {int counter;System.out.printf("%s: Processing lines from %d to %d.\n", Thread.currentThread().getName(), firstRow, lastRow);for (int i = firstRow; i < lastRow; i++) {int row[] = mock.getRow(i);counter = 0;for (int j = 0; j < row.length; j++) {if (row[j] == number) {counter++;}}results.setData(i, counter);}System.out.printf("%s: Lines processed.\n", Thread.currentThread().getName());try {barrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}
}class Grouper implements Runnable {private Results results;public Grouper(Results results) {this.results = results;}@Overridepublic void run() {int finalResult = 0;System.out.printf("Grouper: Processing results...\n");int data[] = results.getData();for (int number : data) {finalResult += number;}System.out.printf("Grouper: Total result: %d.\n", finalResult);}
}

输出:

Mock: There are 1001577 ocurrences of number in generated data.
Thread-0: Processing lines from 0 to 2000.
Thread-3: Processing lines from 6000 to 8000.
Thread-2: Processing lines from 4000 to 6000.
Thread-1: Processing lines from 2000 to 4000.
Thread-4: Processing lines from 8000 to 10000.
Main: The main thread has finished.
Thread-3: Lines processed.
Thread-2: Lines processed.
Thread-4: Lines processed.
Thread-0: Lines processed.
Thread-1: Lines processed.
Grouper: Processing results...
Grouper: Total result: 1001577.
BUILD SUCCESSFUL (total time: 0 seconds)

3、Phaser  

运行阶段性的并发任务。当某些并发任务是分成多个步骤来执行时,那么此机制是非常有用的。Phaser类提供的机制是在每个步骤的结尾同步线程,所以除非全部线程完成第一个步骤,否则线程不能开始进行第二步。

class FileSearch implements Runnable {private String initPath;private String end;private List<String> results;private Phaser phaser;public FileSearch(String initPath, String end, Phaser phaser) {this.initPath = initPath;this.end = end;this.phaser = phaser;results = new ArrayList<>();}private void directoryProcess(File file) {File list[] = file.listFiles();if (list != null) {for (int i = 0; i < list.length; i++) {if (list[i].isDirectory()) {directoryProcess(list[i]);} else {fileProcess(list[i]);}}}}private void fileProcess(File file) {if (file.getName().endsWith(end)) {results.add(file.getAbsolutePath());}}private void filterResults() {List<String> newResults = new ArrayList<>();long actualDate = new Date().getTime();for (int i = 0; i < results.size(); i++) {File file = new File(results.get(i));long fileDate = file.lastModified();if (actualDate - fileDate < TimeUnit.MILLISECONDS.convert(1,TimeUnit.DAYS)) {newResults.add(results.get(i));}}results = newResults;}private boolean checkResults() {if (results.isEmpty()) {System.out.printf("%s: Phase %d: 0 results.\n", Thread.currentThread().getName(), phaser.getPhase());System.out.printf("%s: Phase %d: End.\n", Thread.currentThread().getName(), phaser.getPhase());phaser.arriveAndDeregister();return false;} else {System.out.printf("%s: Phase %d: %d results.\n", Thread.currentThread().getName(), phaser.getPhase(), results.size());phaser.arriveAndAwaitAdvance();return true;}}private void showInfo() {for (int i = 0; i < results.size(); i++) {File file = new File(results.get(i));System.out.printf("%s: %s\n", Thread.currentThread().getName(),file.getAbsolutePath());}phaser.arriveAndAwaitAdvance();}@Overridepublic void run() {phaser.arriveAndAwaitAdvance();System.out.printf("%s: Starting.\n", Thread.currentThread().getName());File file = new File(initPath);if (file.isDirectory()) {directoryProcess(file);}if (!checkResults()) {return;}filterResults();if (!checkResults()) {return;}showInfo();phaser.arriveAndDeregister();System.out.printf("%s: Work completed.\n", Thread.currentThread().getName());}
}class PhaserTest {public static void main(String[] args) {Phaser phaser = new Phaser(3);FileSearch system = new FileSearch("C:\\Windows", "log", phaser);FileSearch apps = new FileSearch("C:\\Program Files", "log", phaser);FileSearch documents = new FileSearch("C:\\Documents And Settings","log", phaser);Thread systemThread = new Thread(system, "System");systemThread.start();Thread appsThread = new Thread(apps, "Apps");appsThread.start();Thread documentsThread = new Thread(documents, "Documents");documentsThread.start();try {systemThread.join();appsThread.join();documentsThread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Terminated: " + phaser.isTerminated());}
}

输出:

Apps: Starting.
System: Starting.
Documents: Starting.
Documents: Phase 1: 0 results.
Documents: Phase 1: End.
Apps: Phase 1: 4 results.
System: Phase 1: 40 results.
Apps: Phase 2: 0 results.
Apps: Phase 2: End.
System: Phase 2: 7 results.
System: C:\Windows\inf\setupapi.app.log
System: C:\Windows\inf\setupapi.dev.log
System: C:\Windows\ServiceProfiles\NetworkService\AppData\Local\Temp\MpCmdRun.log
System: C:\Windows\setupact.log
System: C:\Windows\Temp\MpCmdRun.log
System: C:\Windows\Temp\vminst.log
System: C:\Windows\WindowsUpdate.log
System: Work completed.
Terminated: true

例子2

public class PhaserTest2 {public static void main(String[] args) {MyPhaser phaser = new MyPhaser();Student students[] = new Student[5];for (int i = 0; i < students.length; i++) {students[i] = new Student(phaser);phaser.register();}Thread threads[] = new Thread[students.length];for (int i = 0; i < students.length; i++) {threads[i] = new Thread(students[i], "Student " + i);threads[i].start();}for (int i = 0; i < threads.length; i++) {try {threads[i].join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.printf("Main: The phaser has finished: %s.\n",phaser.isTerminated());}
}class MyPhaser extends Phaser {@Overrideprotected boolean onAdvance(int phase, int registeredParties) {switch (phase) {case 0:return studentsArrived();case 1:return finishFirstExercise();case 2:return finishSecondExercise();case 3:return finishExam();default:return true;}}private boolean studentsArrived() {System.out.printf("Phaser: The exam are going to start. The students are ready.\n");System.out.printf("Phaser: We have %d students.\n",getRegisteredParties());return false;}private boolean finishFirstExercise() {System.out.printf("Phaser: All the students have finished the first exercise.\n");System.out.printf("Phaser: It's time for the second one.\n");return false;}private boolean finishSecondExercise() {System.out.printf("Phaser: All the students have finished the second exercise.\n");System.out.printf("Phaser: It's time for the third one.\n");return false;}private boolean finishExam() {System.out.printf("Phaser: All the students have finished the exam.\n");System.out.printf("Phaser: Thank you for your time.\n");return true;}
}class Student implements Runnable {private Phaser phaser;public Student(Phaser phaser) {this.phaser = phaser;}@Overridepublic void run() {System.out.printf("%s: Has arrived to do the exam. %s\n", Thread.currentThread().getName(), new Date());phaser.arriveAndAwaitAdvance();System.out.printf("%s: Is going to do the first exercise. %s\n",Thread.currentThread().getName(), new Date());doExercise1();System.out.printf("%s: Has done the first exercise. %s\n", Thread.currentThread().getName(), new Date());phaser.arriveAndAwaitAdvance();System.out.printf("%s: Is going to do the second exercise.%s\n",Thread.currentThread().getName(), new Date());doExercise2();System.out.printf("%s: Has done the second exercise. %s\n", Thread.currentThread().getName(), new Date());phaser.arriveAndAwaitAdvance();System.out.printf("%s: Is going to do the third exercise. %s\n",Thread.currentThread().getName(), new Date());doExercise3();System.out.printf("%s: Has finished the exam. %s\n", Thread.currentThread().getName(), new Date());phaser.arriveAndAwaitAdvance();}private void doExercise1() {try {long duration = (long) (Math.random() * 10);TimeUnit.SECONDS.sleep(duration);} catch (InterruptedException e) {e.printStackTrace();}}private void doExercise2() {try {long duration = (long) (Math.random() * 10);TimeUnit.SECONDS.sleep(duration);} catch (InterruptedException e) {e.printStackTrace();}}private void doExercise3() {try {long duration = (long) (Math.random() * 10);TimeUnit.SECONDS.sleep(duration);} catch (InterruptedException e) {e.printStackTrace();}}
}

输出:

Student 2: Has arrived to do the exam. Sun Sep 21 16:52:37 CST 2014
Student 4: Has arrived to do the exam. Sun Sep 21 16:52:37 CST 2014
Student 0: Has arrived to do the exam. Sun Sep 21 16:52:37 CST 2014
Student 3: Has arrived to do the exam. Sun Sep 21 16:52:37 CST 2014
Student 1: Has arrived to do the exam. Sun Sep 21 16:52:37 CST 2014
Phaser: The exam are going to start. The students are ready.
Phaser: We have 5 students.
Student 3: Is going to do the first exercise. Sun Sep 21 16:52:37 CST 2014
Student 4: Is going to do the first exercise. Sun Sep 21 16:52:37 CST 2014
Student 0: Is going to do the first exercise. Sun Sep 21 16:52:37 CST 2014
Student 2: Is going to do the first exercise. Sun Sep 21 16:52:37 CST 2014
Student 1: Is going to do the first exercise. Sun Sep 21 16:52:37 CST 2014
Student 4: Has done the first exercise. Sun Sep 21 16:52:39 CST 2014
Student 0: Has done the first exercise. Sun Sep 21 16:52:39 CST 2014
Student 3: Has done the first exercise. Sun Sep 21 16:52:43 CST 2014
Student 1: Has done the first exercise. Sun Sep 21 16:52:43 CST 2014
Student 2: Has done the first exercise. Sun Sep 21 16:52:46 CST 2014
Phaser: All the students have finished the first exercise.
Phaser: It's time for the second one.
Student 0: Is going to do the second exercise.Sun Sep 21 16:52:46 CST 2014
Student 4: Is going to do the second exercise.Sun Sep 21 16:52:46 CST 2014
Student 2: Is going to do the second exercise.Sun Sep 21 16:52:46 CST 2014
Student 1: Is going to do the second exercise.Sun Sep 21 16:52:46 CST 2014
Student 3: Is going to do the second exercise.Sun Sep 21 16:52:46 CST 2014
Student 4: Has done the second exercise. Sun Sep 21 16:52:51 CST 2014
Student 0: Has done the second exercise. Sun Sep 21 16:52:52 CST 2014
Student 1: Has done the second exercise. Sun Sep 21 16:52:52 CST 2014
Student 2: Has done the second exercise. Sun Sep 21 16:52:55 CST 2014
Student 3: Has done the second exercise. Sun Sep 21 16:52:55 CST 2014
Phaser: All the students have finished the second exercise.
Phaser: It's time for the third one.
Student 0: Is going to do the third exercise. Sun Sep 21 16:52:55 CST 2014
Student 2: Is going to do the third exercise. Sun Sep 21 16:52:55 CST 2014
Student 1: Is going to do the third exercise. Sun Sep 21 16:52:55 CST 2014
Student 3: Is going to do the third exercise. Sun Sep 21 16:52:55 CST 2014
Student 4: Is going to do the third exercise. Sun Sep 21 16:52:55 CST 2014
Student 0: Has finished the exam. Sun Sep 21 16:52:58 CST 2014
Student 4: Has finished the exam. Sun Sep 21 16:52:58 CST 2014
Student 2: Has finished the exam. Sun Sep 21 16:53:02 CST 2014
Student 3: Has finished the exam. Sun Sep 21 16:53:02 CST 2014
Student 1: Has finished the exam. Sun Sep 21 16:53:03 CST 2014
Phaser: All the students have finished the exam.
Phaser: Thank you for your time.
Main: The phaser has finished: true.

4、Exchanger 

Exchanger 类允许在2个线程间定义同步点,当2个线程到达这个点,他们相互交换数据类型,使用第一个线程的数据类型变成第二个的,然后第二个线程的数据类型变成第一个的。

public class ExchangerTest {public static void main(String[] args) {List<String> buffer1 = new ArrayList<String>();List<String> buffer2 = new ArrayList<String>();Exchanger<List<String>> exchanger = new Exchanger<List<String>>();Producer producer = new Producer(buffer1, exchanger);Consumer consumer = new Consumer(buffer2, exchanger);Thread threadProducer = new Thread(producer);Thread threadConsumer = new Thread(consumer);threadProducer.start();threadConsumer.start();}
}class Producer implements Runnable {private List<String> buffer;private final Exchanger<List<String>> exchanger;public Producer(List<String> buffer, Exchanger<List<String>> exchanger) {this.buffer = buffer;this.exchanger = exchanger;}@Overridepublic void run() {int cycle = 1;for (int i = 0; i < 10; i++) {System.out.printf("Producer: Cycle %d\n", cycle);for (int j = 0; j < 10; j++) {String message = "Event " + ((i * 10) + j);System.out.printf("Producer: %s\n", message);buffer.add(message);}try {buffer = exchanger.exchange(buffer);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Producer: " + buffer.size());cycle++;}}
}class Consumer implements Runnable {private List<String> buffer;private final Exchanger<List<String>> exchanger;public Consumer(List<String> buffer, Exchanger<List<String>> exchanger) {this.buffer = buffer;this.exchanger = exchanger;}@Overridepublic void run() {int cycle = 1;for (int i = 0; i < 10; i++) {System.out.printf("Consumer: Cycle %d\n", cycle);try {buffer = exchanger.exchange(buffer);} catch (InterruptedException e) {e.printStackTrace();}for (int j = 0; j < 10; j++) {String message = buffer.get(0);System.out.println("Consumer: " + message);buffer.remove(0);}cycle++;}}
}

转载于:https://www.cnblogs.com/leeeee/p/7276432.html

《Java 7 并发编程指南》学习概要 (3)Semaphore, CountDownLatch, CyclicBarrier , Phaser, Exchanger...相关推荐

  1. Java 7 并发编程指南

    原文是发表在并发编程网上翻译后的 <Java 7 并发编程指南>,这里对其中的目录做个更加详细的描述,并且写出了重点说明,方便日后快速查阅.建议仔细查看每节的代码实现,非常具有参考价值.可 ...

  2. @冰河老师的巨作,人手一册的Java高并发编程指南,值得了解一下

    还真不好意思,这次 Java Thread Pool 惊爆了! 高并发是每一个后端开发工程师都头疼的问题,也是工程师能力的分水岭.要想基于JDK核心技术,玩转高并发编程,必须要好好修炼内功才行. 文章 ...

  3. Java并发编程实战基础概要

    文章目录 Java并发编程实战基础概要 开篇 多线程问题有啥难点呢? 为啥要学习并发编程? 并发问题的根源是什么? CPU切换线程执导致的原子性问题是如何发生的? 缓存导致的可见性问题是如何发生的? ...

  4. Java高并发编程学习(三)java.util.concurrent包

    简介 我们已经学习了形成Java并发程序设计基础的底层构建块,但对于实际编程来说,应该尽可能远离底层结构.使用由并发处理的专业人士实现的较高层次的结构要方便得多.要安全得多.例如,对于许多线程问题,可 ...

  5. Java并发编程艺术学习笔记(五)

    Java并发编程艺术学习笔记(五) Java并发容器和框架 Java为开发者也提供了许多开发容器和框架,可以从每节的原理分析来学习其中精妙的并发程序. 一.ConcurrentHashMap的实现原理 ...

  6. Java 7并发编程实战手册

    2019独角兽企业重金招聘Python工程师标准>>> Java 7并发编程实战手册 本书是 Java 7 并发编程的实战指南,介绍了Java 7 并发API 中大部分重要而有用的机 ...

  7. 阿里云 刷新缓存 java_【从入门到放弃-Java】并发编程-NIO-Buffer

    前言 上篇[从入门到放弃-Java]并发编程-NIO-Channel中我们学习到channel是双向通道,数据通过channel在实体(文件.socket)和缓冲区(buffer)中可以双向传输. 本 ...

  8. 操作系统锁的实现方法有哪几种_「从入门到放弃-Java」并发编程-锁-synchronized...

    简介 上篇[从入门到放弃-Java]并发编程-线程安全中,我们了解到,可以通过加锁机制来保护共享对象,来实现线程安全. synchronized是java提供的一种内置的锁机制.通过synchroni ...

  9. 【从入门到放弃-Java】并发编程-锁-synchronized

    简介 上篇[从入门到放弃-Java]并发编程-线程安全中,我们了解到,可以通过加锁机制来保护共享对象,来实现线程安全. synchronized是java提供的一种内置的锁机制.通过synchroni ...

最新文章

  1. 腾讯博士:年薪60万辞职去教书,你想要哪种生活?
  2. 适用于Android的OpenSL ES指南-OpenSL ES的Android扩展
  3. 【原】storm源码之一个class解决nimbus单点问题
  4. 在 Spring中 创建 JavaBean
  5. 在RHEL7.8上安装配置tomcat
  6. cks32和stm32_cks子,间谍,局部Mo子和短管
  7. 组网胖模式_胖瘦AP组网优劣对比,你知道吗?
  8. SQL SERVER游标浅析
  9. VS2010解决闪退的方法
  10. linux 删除文件 例外,linux 删除文件,某个文件例外
  11. Sql注入基础_mysql注入
  12. 如何查看局域网内所有在线的ip
  13. 强学习器------随机森林
  14. 18-Halcon机器视觉实例入门:图像滤波-各向异性滤波
  15. 挂耳式骨传导蓝牙耳机,2021骨传导耳机推荐
  16. 转:使用rz上传压缩文件遇到的一些坑
  17. Scrapy图片分类异步下载
  18. java shp文件_java发布shp数据
  19. Java 亚马逊Amazon spapi对接开发,java Sdk,授权和接口访问步骤详细说明
  20. 利用ARCGIS和QGIS画等值线图

热门文章

  1. Source Insight 4.0的使用(转)
  2. linux智能电压表设计与实现,STC89C51数字电压表
  3. 怎么开启队友无伤_和平精英暗夜危机无敌点位送上!不仅无伤打僵尸 敌人还看不到你...
  4. matlab 正则化表达式_MATLAB 正则表达式(一)(转)
  5. Java日志框架-logback的介绍及配置使用方法(纯Java工程)
  6. Java word 内容读取
  7. spss文件 服务器登录,spss连接远程服务器
  8. 载入页面时与服务器的连接被重置。_快捷指令打不开怎么回事?安装快捷指令无法载入的解决办法...
  9. nginx 4层代理配置
  10. K-means算法应用:图片压缩