一、死锁*
1.1 概述
当第一个线程拥有A对象锁标记,并等待B对象锁标记,同时第二个线程拥有B对象锁标记,并等待A对象锁标记时,产生死锁。 一个线程可以同时拥有多个对象的锁标记,当线程阻塞时,不会释放已经拥有的钡怀记,由此可能造成死锁。
1.2 代码实现
public class Demo01 {
public static void main ( String [ ] args) {
ThreadBB bb = new ThreadBB ( ) ;
ThreadCC cc = new ThreadCC ( ) ;
bb. start ( ) ;
cc. start ( ) ;
}
}
class LockObject {
public static final Object LOCK_A = new Object ( ) ;
public static final Object LOCK_B = new Object ( ) ;
}
class ThreadBB extends Thread {
@Override
public void run ( ) {
synchronized ( LockObject . LOCK_A ) {
System . out. println ( "BB获取到第一根筷子LOCK_A,正在尝试获取第二根筷子LOCK_B" ) ;
synchronized ( LockObject . LOCK_B ) {
System . out. println ( "BB获取到筷子LOCK_A和筷子LOCK_B,可以开动啦" ) ;
}
}
}
}
class ThreadCC extends Thread {
@Override
public void run ( ) {
synchronized ( LockObject . LOCK_B ) {
System . out. println ( "CC获取到第一根筷子LOCK_B,正在尝试获取第二根筷子LOCK_A" ) ;
synchronized ( LockObject . LOCK_A ) {
System . out. println ( "CC获取到筷子LOCK_A和筷子LOCK_B,可以开动啦" ) ;
}
}
}
}
二、生产者和消费者
2.1 概述
若干个生产者在生产产品,这些产品将提供给若干个消费者去消费 为了使生产者和消费者能并发执行,在两者之间设置一个能存储多个产品的缓冲区 生产者将生产的产品放入缓冲区中,消费者从缓冲区中取走产品进行消费 显然生产者和消费者之间必须保持同步
即不允许消费者到一个空的缓冲区中取产品 也不允许生产者向一个满的缓冲区中放入产品。
2.2 第一版
public class Demo01 {
public static void main ( String [ ] args) {
Card card = new Card ( ) ;
ThreadBB bb = new ThreadBB ( card) ;
ThreadCC cc = new ThreadCC ( card) ;
bb. start ( ) ;
cc. start ( ) ;
}
}
class Card {
private int money = 0 ;
public int getMoney ( ) {
return money;
}
public void setMoney ( int money) {
this . money = money;
}
}
class ThreadBB extends Thread {
private Card card;
public ThreadBB ( Card card) {
super ( ) ;
this . card = card;
}
@Override
public void run ( ) {
for ( int i = 1 ; i <= 12 ; i++ ) {
card. setMoney ( card. getMoney ( ) - 5000 ) ;
System . out. println ( "BB取出了5000,余额" + card. getMoney ( ) ) ;
}
}
}
class ThreadCC extends Thread {
private Card card;
public ThreadCC ( Card card) {
super ( ) ;
this . card = card;
}
@Override
public void run ( ) {
for ( int i = 1 ; i <= 12 ; i++ ) {
card. setMoney ( card. getMoney ( ) + 5000 ) ;
System . out. println ( "CC存入了5000,余额" + card. getMoney ( ) ) ;
}
}
}
2.3 第二版
public class Demo01 {
public static void main ( String [ ] args) {
Card card = new Card ( ) ;
ThreadBB bb = new ThreadBB ( card) ;
ThreadCC cc = new ThreadCC ( card) ;
bb. start ( ) ;
cc. start ( ) ;
}
}
class Card {
private int money = 0 ;
public int getMoney ( ) {
return money;
}
public void setMoney ( int money) {
this . money = money;
}
}
class ThreadBB extends Thread {
private Card card;
public ThreadBB ( Card card) {
super ( ) ;
this . card = card;
}
@Override
public void run ( ) {
for ( int i = 1 ; i <= 12 ; i++ ) {
synchronized ( Card . class ) {
if ( card. getMoney ( ) <= 0 ) {
i-- ;
continue ;
}
card. setMoney ( card. getMoney ( ) - 5000 ) ;
System . out. println ( "BB取出了5000,余额" + card. getMoney ( ) ) ;
try {
Thread . sleep ( 100 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
class ThreadCC extends Thread {
private Card card;
public ThreadCC ( Card card) {
super ( ) ;
this . card = card;
}
@Override
public void run ( ) {
for ( int i = 1 ; i <= 12 ; i++ ) {
if ( card. getMoney ( ) > 0 ) {
i-- ;
continue ;
}
synchronized ( Card . class ) {
card. setMoney ( card. getMoney ( ) + 5000 ) ;
System . out. println ( "CC存入了5000,余额" + card. getMoney ( ) ) ;
try {
Thread . sleep ( 100 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
2.4 第三版
public class Demo01 {
public static void main ( String [ ] args) {
Card card = new Card ( ) ;
ThreadBB bb = new ThreadBB ( card) ;
ThreadCC cc = new ThreadCC ( card) ;
bb. start ( ) ;
cc. start ( ) ;
}
}
class Card {
private int money = 0 ;
public synchronized void saveMoney ( ) {
if ( money > 0 ) {
try {
this . wait ( ) ;
Thread . sleep ( 500 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
money += 5000 ;
System . out. println ( "CC存入了5000,余额" + money) ;
this . notify ( ) ;
}
public synchronized void takeMoney ( ) {
if ( money <= 0 ) {
try {
this . wait ( ) ;
Thread . sleep ( 500 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
money -= 5000 ;
System . out. println ( "BB取出了5000,余额" + money) ;
this . notify ( ) ;
}
}
class ThreadBB extends Thread {
private Card card;
public ThreadBB ( Card card) {
super ( ) ;
this . card = card;
}
@Override
public void run ( ) {
for ( int i = 1 ; i <= 12 ; i++ ) {
card. takeMoney ( ) ;
}
}
}
class ThreadCC extends Thread {
private Card card;
public ThreadCC ( Card card) {
super ( ) ;
this . card = card;
}
@Override
public void run ( ) {
for ( int i = 1 ; i <= 12 ; i++ ) {
card. saveMoney ( ) ;
}
}
}
三、线程池
3.1 概述
线程的创建和销毁会占用大量的资源
可以限制线程创建的数量,复用创建的线程,把线程放入一个容器
3.2 线程池入门
import java. util. concurrent. ExecutorService ;
import java. util. concurrent. Executors ;
public class Demo02 {
public static void main ( String [ ] args) throws InterruptedException {
ExecutorService es = Executors . newFixedThreadPool ( 2 ) ;
es. submit ( new Runnable ( ) {
@Override
public void run ( ) {
for ( int i = 0 ; i < 5 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "==>" + i) ;
try {
Thread . sleep ( 200 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
} ) ;
es. submit ( new Runnable ( ) {
@Override
public void run ( ) {
for ( int i = 0 ; i < 5 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "==>" + i) ;
try {
Thread . sleep ( 200 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
} ) ;
es. submit ( new Runnable ( ) {
@Override
public void run ( ) {
for ( int i = 0 ; i < 5 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "==>" + i) ;
try {
Thread . sleep ( 200 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
} ) ;
es. shutdown ( ) ;
System . out. println ( es) ;
Thread . sleep ( 3000 ) ;
System . out. println ( es) ;
}
}
3.3 线程池API
Executor
ExecutorService
声明的线程池对象类型 有子类ThreadPoolExecutor
boolean isTerminated ( )
如果关闭后所有任务都已完成,则返回 true 。
void shutdown ( )
启动一次顺序关闭,执行以前提交的任务,但不接受新任务。
< T > Future < T > submit ( Callable < T > task)
提交一个返回值的任务用于执行,返回一个表示任务结果的 Future 。
Future < ? > submit ( Runnable task)
提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future 。
Executors
static ExecutorService newCachedThreadPool ( )
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
static ExecutorService newFixedThreadPool ( int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
static ScheduledExecutorService newScheduledThreadPool ( int corePoolSize)
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
static ExecutorService newSingleThreadExecutor ( )
创建一个使用单个 worker 线程的 Executor ,以无界队列方式来运行该线程。
Callable
返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call
的方法。 Callable
接口类似于 Runnable
,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable
不会返回结果,并且无法抛出经过检查的异常。
Future
Future
表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。 计算完成后只能使用 get
方法来获取结果
3.4 多线程计算数组总和【掌握】
import java. util. concurrent. Callable ;
import java. util. concurrent. ExecutionException ;
import java. util. concurrent. ExecutorService ;
import java. util. concurrent. Executors ;
import java. util. concurrent. Future ;
public class Demo06 {
public static void main ( String [ ] args) throws InterruptedException , ExecutionException {
int [ ] [ ] arr = {
{ 12 , 565 , 98 , 2 , 4 , 67 , 8 , 322 , 657 , 97 , 656 } ,
{ 9 , 766 , 5 , 456 , 67 , 8 , 78 , 8 , 34 , 343 , 37632 } ,
{ 42314 , 7 , 3 , 76 , 1356763 , 45 , 85 , 464 } ,
{ 7633 , 24 , 876432 , 8 , 7434 , 5765 , 323 , 46 , 5 }
} ;
ExecutorService es = Executors . newFixedThreadPool ( 4 ) ;
Future < Integer > future00 = es. submit ( new CalculatCallable ( arr[ 0 ] ) ) ;
Future < Integer > future01 = es. submit ( new CalculatCallable ( arr[ 1 ] ) ) ;
Future < Integer > future02 = es. submit ( new CalculatCallable ( arr[ 2 ] ) ) ;
Future < Integer > future03 = es. submit ( new CalculatCallable ( arr[ 3 ] ) ) ;
es. shutdown ( ) ;
System . out. println ( future00. get ( ) + future01. get ( ) + future02. get ( ) + future03. get ( ) ) ;
System . out. println ( 39406 + 2488 + 1399757 + 897670 ) ;
}
}
class CalculatCallable implements Callable < Integer > {
private int [ ] arr;
public CalculatCallable ( int [ ] arr) {
super ( ) ;
this . arr = arr;
}
@Override
public Integer call ( ) throws Exception {
int sum = 0 ;
for ( int i = 0 ; i < arr. length; i++ ) {
sum += arr[ i] ;
}
return sum;
}
}
四、Lock
4.1 概述
Lock
提供了比使用 synchronized
方法和语句更广泛的锁定操作。
能实现synchronized的所有参数 更加的灵活、高效
4.2 核心方法
lock
锁定
unLock
解锁,必须执行,放在finally 代码块中执行
4.3 ReentrantLock
一个可重入的互斥锁 Lock
,它具有与使用 synchronized
方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。 可重入
互斥
A线程执行的时候B线程阻塞 B线程执行的时候A线程阻塞 卖票
import java. util. concurrent. locks. ReentrantLock ;
public class Demo01 {
public static void main ( String [ ] args) {
TicketThread t01 = new TicketThread ( ) ;
TicketThread t02 = new TicketThread ( ) ;
TicketThread t03 = new TicketThread ( ) ;
TicketThread t04 = new TicketThread ( ) ;
t01. setName ( "一号窗口" ) ;
t02. setName ( "22号窗口" ) ;
t03. setName ( "叁号窗口" ) ;
t04. setName ( "④号窗口" ) ;
t01. start ( ) ;
t02. start ( ) ;
t03. start ( ) ;
t04. start ( ) ;
}
}
class TicketThread extends Thread {
private static int ticket = 100 ;
private static ReentrantLock lock = new ReentrantLock ( ) ;
@Override
public void run ( ) {
while ( true ) {
lock. lock ( ) ;
try {
if ( ticket <= 0 ) {
break ;
}
ticket-- ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "卖出了第" + ( 100 - ticket) + "张票,还剩下" + ticket) ;
} finally {
lock. unlock ( ) ;
}
}
}
}
import java. util. Arrays ;
import java. util. concurrent. locks. ReentrantLock ;
public class Demo02 {
public static void main ( String [ ] args) throws InterruptedException {
ArrSrc arrSrc = new ArrSrc ( ) ;
ThreadA a = new ThreadA ( arrSrc) ;
ThreadB b = new ThreadB ( arrSrc) ;
a. start ( ) ;
b. start ( ) ;
Thread . sleep ( 10 ) ;
System . out. println ( arrSrc) ;
}
}
class ArrSrc {
String [ ] arr = new String [ 5 ] ;
int index = 0 ;
private static ReentrantLock lock = new ReentrantLock ( ) ;
public void modifyArr ( String str) {
lock. lock ( ) ;
try {
arr[ index] = str;
index++ ;
} finally {
lock. unlock ( ) ;
}
}
@Override
public String toString ( ) {
return "ArrSrc [arr=" + Arrays . toString ( arr) + ", index=" + index + "]" ;
}
}
class ThreadA extends Thread {
private ArrSrc arrSrc;
public ThreadA ( ArrSrc arrSrc) {
super ( ) ;
this . arrSrc = arrSrc;
}
@Override
public void run ( ) {
arrSrc. modifyArr ( "Hello" ) ;
}
}
class ThreadB extends Thread {
private ArrSrc arrSrc;
public ThreadB ( ArrSrc arrSrc) {
super ( ) ;
this . arrSrc = arrSrc;
}
@Override
public void run ( ) {
arrSrc. modifyArr ( "World" ) ;
}
}
4.4 读写锁
import java. util. concurrent. ExecutorService ;
import java. util. concurrent. Executors ;
import java. util. concurrent. locks. ReentrantLock ;
import java. util. concurrent. locks. ReentrantReadWriteLock ;
import java. util. concurrent. locks. ReentrantReadWriteLock . ReadLock ;
import java. util. concurrent. locks. ReentrantReadWriteLock . WriteLock ;
public class Demo03 {
public static void main ( String [ ] args) {
MyClass mc = new MyClass ( ) ;
long startTime = System . currentTimeMillis ( ) ;
ExecutorService es = Executors . newFixedThreadPool ( 20 ) ;
for ( int i = 0 ; i < 18 ; i++ ) {
es. submit ( new Runnable ( ) {
@Override
public void run ( ) {
mc. getValue ( ) ;
}
} ) ;
}
for ( int i = 0 ; i < 2 ; i++ ) {
es. submit ( new Runnable ( ) {
@Override
public void run ( ) {
mc. setValue ( "Hello" ) ;
}
} ) ;
}
es. shutdown ( ) ;
while ( ! es. isTerminated ( ) ) { }
long endTime = System . currentTimeMillis ( ) ;
System . out. println ( endTime - startTime) ;
}
}
class MyClass {
private ReentrantLock lock = new ReentrantLock ( ) ;
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock ( ) ;
ReadLock readLock = readWriteLock. readLock ( ) ;
WriteLock writeLock = readWriteLock. writeLock ( ) ;
private String value;
public String getValue ( ) {
readLock. lock ( ) ;
try {
Thread . sleep ( 1000 ) ;
return value;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
} finally {
readLock. unlock ( ) ;
}
return value;
}
public void setValue ( String value) {
writeLock. lock ( ) ;
try {
this . value = value;
Thread . sleep ( 1000 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
} finally {
writeLock. unlock ( ) ;
}
}
}