同步代碼塊
SynchronizedTest類,用來表示取票功能
package concurency.chapter6;
public class SynchronizedTest implements Runnable {
public static final int MAX = 250;
private int index = 0;
@Override
public void run() {
while(true) {
if(ticket())
break;
}
}
// synchronized 此時鎖的是 this 鎖的是一個對象,别弄錯了
private synchronized boolean ticket() {
if(index >= MAX)
return true;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + (++index));
return false;
}
}
Ticket 模拟遊樂園放票
package concurency.chapter6;
public class Ticket {
public static void main(String[] args) {
final SynchronizedTest synRunnable = new SynchronizedTest();
Thread t1 = new Thread(synRunnable, "視窗1");
Thread t2 = new Thread(synRunnable, "視窗2");
Thread t3 = new Thread(synRunnable, "視窗3");
t1.start(); t2.start(); t3.start();
}
}
synchronized
同步方法時,其實是同步的this對象
synchronized
下面可以證明
package concurency.chapter6;
public class SynchronizedThis {
public static void main(String[] args) {
LockThis l1 = new LockThis();
new Thread("thread1"){
@Override
public void run() {
l1.m1();
}
}.start();
new Thread("thread2"){
@Override
public void run() {
l1.m2();
}
}.start();
}
}
class LockThis {
public synchronized void m1() {
try {
System.out.println(Thread.currentThread().getName() + " method1");
Thread.sleep(3_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void m2() {
try {
System.out.println(Thread.currentThread().getName() + " method2");
Thread.sleep(3_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized
同步靜态方法時,其實是同步的class
synchronized
package concurency.chapter6;
public class SynchronizedThis {
public static void main(String[] args) {
new Thread("thread1"){
@Override
public void run() {
LockThis.m1();
}
}.start();
new Thread("thread2"){
@Override
public void run() {
LockThis.m2();
}
}.start();
}
}
class LockThis {
public static synchronized void m1() {
try {
System.out.println(Thread.currentThread().getName() + " method1");
Thread.sleep(3_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void m2() {
try {
System.out.println(Thread.currentThread().getName() + " method2");
Thread.sleep(3_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
死鎖小案例
Service1 兩個方法. m1和m2
package concurency.chapter7;
public class Service1 {
private final Object lock1 = new Object();
public Service2 service2;
public Service1(Service2 service2) {
this.service2 = service2;
}
public void m1() {
synchronized(lock1) {
System.out.println("---m1---");
service2.s1();
}
}
public void m2() {
synchronized(lock1) {
System.out.println("---m2---");
}
}
}
Service2 兩個方法, s1和s2
package concurency.chapter7;
public class Service2 {
public void s1() {
synchronized (lock2) {
System.out.println("---s1---");
}
}
public void s2() {
synchronized (lock2) {
System.out.println("---s2---");
service1.m2();
}
}
private final Object lock2 = new Object();
public Service1 service1;
void setService1(Service1 service1) {
this.service1 = service1;
}
}
死鎖嘗試
package concurency.chapter7;
public class DeadLockTest {
public static void main(String[] args) {
Service2 service2 = new Service2();
Service1 service1 = new Service1(service2);
service2.setService1(service1);
new Thread() {
@Override
public void run() {
while(true)
service2.s2();
}
}.start();
new Thread() {
@Override
public void run() {
while(true)
service1.m1();
}
}.start();
}
}
jstack指令檢視線程
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x0000000017ceddd8 (object 0x00000000d5f7e150, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x0000000017cec938 (object 0x00000000d5f806c8, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at concurency.chapter7.Service2.s1(Service2.java:6)
- waiting to lock <0x00000000d5f7e150> (a java.lang.Object)
at concurency.chapter7.Service1.m1(Service1.java:16)
- locked <0x00000000d5f806c8> (a java.lang.Object)
at concurency.chapter7.DeadLockTest$2.run(DeadLockTest.java:21)
"Thread-0":
at concurency.chapter7.Service1.m2(Service1.java:21)
- waiting to lock <0x00000000d5f806c8> (a java.lang.Object)
at concurency.chapter7.Service2.s2(Service2.java:13)
- locked <0x00000000d5f7e150> (a java.lang.Object)
at concurency.chapter7.DeadLockTest$1.run(DeadLockTest.java:13)
Found 1 deadlock.
生産者與消費者
單個生産者 單個消費者
package concurency.chapter8;
public class ConsumerAndProducer {
int index = 0;
private final Object LOCK = new Object();
volatile boolean isProduce = false;
private void produce() {
synchronized(LOCK) {
if( isProduce ) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 沒生産過
index++;
System.out.println("product->" + index);
isProduce = true;
LOCK.notify();
}
}
}
private void consume() {
synchronized (LOCK) {
if(isProduce) {
System.out.println("consume->" + index);
isProduce = false;
LOCK.notify();
} else {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ConsumerAndProducer cp = new ConsumerAndProducer();
new Thread("producer") {
@Override
public void run() {
while(true)
cp.produce();
}
}.start();
new Thread("consumer") {
@Override
public void run() {
while (true)
cp.consume();
}
}.start();
}
}
多個生産者 多個消費者
package concurency.chapter8;
import java.util.stream.Stream;
public class ConsumerAndProducerV2 {
int index = 0;
private final Object LOCK = new Object();
volatile boolean isProduce = false;
private void produce() {
synchronized (LOCK) {
while(isProduce) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index++;
System.out.println(Thread.currentThread().getName() + " " + index);
isProduce = true;
LOCK.notifyAll();
}
}
private void consume() {
synchronized (LOCK) {
while(!isProduce) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + index);
isProduce = false;
LOCK.notifyAll();
}
}
public static void main(String[] args) {
ConsumerAndProducerV2 cp = new ConsumerAndProducerV2();
Stream.of("Producer1", "Producer2", "Producer3").forEach((name)->{
new Thread(name) {
@Override
public void run() {
while (true) {
cp.produce();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
});
Stream.of("Consumer1", "Consumer2", "Consumer3", "Consumer4").forEach((name)->{
new Thread(name) {
@Override
public void run() {
while(true) {
cp.consume();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
});
}
}
wait和sleep差別
-
是sleep
的方法,而Thread
是wait
的方法object
-
will not release the monitor(LOCK), butsleep
will release the monitor(LOCK) and add to the object monitor waiting queue.wait
- use
not depend on the monitor, butsleep
need(synchronized).wait
-
not need to be wakeup, butsleep
must need to notify.wait
資料采集多線程案例
package concurency.chapter8;
import java.util.*;
/**
* @author draymonder
* @Date 2019/02/14
*/
public class DataCapture {
private static final Object LOCK = new Object();
private static final int MAX = 5;
private static LinkedList<Controller> list = new LinkedList<>();
public static void main(String[] args) {
ArrayList<Thread> threads = new ArrayList<>();
// 開辟10個線程, 每個線程采集資料
Arrays.asList("Mac1", "Mac2", "Mac3", "Mac4", "Mac5", "Mac6", "Mac7", "Mac8", "Mac9", "Mac10").stream()
.map(DataCapture::createDataCaptureThread).forEach(dataCaptureThread->{
dataCaptureThread.start();
// 放入threads List中
threads.add(dataCaptureThread);
});
// main線程等這10個線程 執行完再結束
threads.forEach((thread)->{
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Optional.of("the data capture have finished").ifPresent(System.out::println);
}
private static Thread createDataCaptureThread(String name) {
return new Thread(()->{
Optional.of(Thread.currentThread().getName() + " is begin").ifPresent(System.out::println);
// 如果大于等于5個線程,後面的線程就等待
synchronized (LOCK) {
while(list.size() >= MAX) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(new Controller());
}
Optional.of(Thread.currentThread().getName() + " is running").ifPresent(System.out::println);
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 執行完畢
synchronized (LOCK) {
Optional.of(Thread.currentThread().getName() + " end").ifPresent(System.out::println);
// 執行完 删除一個
list.removeFirst();
LOCK.notifyAll();
}
},name);
}
static class Controller{}
}
執行結果
Mac1 is begin
Mac1 is running
Mac2 is begin
Mac2 is running
Mac3 is begin
Mac3 is running
Mac4 is begin
Mac4 is running
Mac5 is begin
Mac5 is running
Mac6 is begin
Mac7 is begin
Mac8 is begin
Mac9 is begin
Mac10 is begin
Mac1 end
Mac10 is running
Mac2 end
Mac6 is running
Mac3 end
Mac9 is running
Mac4 end
Mac7 is running
Mac5 end
Mac8 is running
Mac10 end
Mac9 end
Mac7 end
Mac6 end
Mac8 end
the data capture have finished