Java 多线程案例
同步代码块
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对象
下面可以证明
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
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
的方法sleep
will not release the monitor(LOCK), butwait
will release the monitor(LOCK) and add to the object monitor waiting queue.- use
sleep
not depend on the monitor, butwait
need(synchronized). sleep
not need to be wakeup, butwait
must need to notify.
数据采集多线程案例
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