### 死锁 死锁是一种错误,实际开发中需要注意避免这种错误的出现。 ```java public class Chopsticks { } ``` ```java public class DeadLockRunnable implements Runnable { public int num; private static Chopsticks chopsticks1 = new Chopsticks(); private static Chopsticks chopsticks2 = new Chopsticks(); @Override public void run() { // TODO Auto-generated method stub if(num == 1) { System.out.println(Thread.currentThread().getName()+"获取到chopsticks1,等待获取chopsticks2"); synchronized (chopsticks1) { try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (chopsticks2) { System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } if(num == 2) { System.out.println(Thread.currentThread().getName()+"获取到chopsticks2,等待获取chopsticks1"); synchronized (chopsticks2) { try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (chopsticks1) { System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } } } ``` ```java public class Test { public static void main(String[] args) { DeadLockRunnable deadLockRunnable1 = new DeadLockRunnable(); deadLockRunnable1.num=1; DeadLockRunnable deadLockRunnable2 = new DeadLockRunnable(); deadLockRunnable2.num=2; Thread thread = new Thread(deadLockRunnable1,"张三"); Thread thread2 = new Thread(deadLockRunnable2,"李四"); thread.start(); try { Thread.currentThread().sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } thread2.start(); } } ``` ### 重入锁 重入锁是实现线程同步的另外一种方式,可以看作是synchronized的升级,synchronized是通过JVM实现的,重入锁是通过JDK实现的。 重入锁的特点: 可以给同一个资源添加多个锁,同时解锁的方式与synchronized也有不同,synchronized的锁是线程执行完毕之后自动释放,重入锁必须手动释放。 可中断是指某个线程在等待获取锁的过程中可以主动终止线程,通过调用 lockInterruptibly() 方法来实现。 重入锁还具备限时性的特点,指可以判断某个线程在一定的时间内能否获取锁,通过调用tryLock(long timeout,TimeUnit unit)方法来实现,其中timeout指时间数值,unit指时间单位,返回值是boolean,true 表示在该时间段内可以获取锁,false表示在该时间段内没有获取锁。 ### 生产者消费者模式 在一个生产环境中,生产者和消费者在同一个时间段内共享同一块缓冲区,生产者负责向缓冲区中添加数据,消费者负责从缓冲区中取出数据,以生产汉堡和消费汉堡为例来实现生产者消费者模式。 ```java public class Hamburger { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Hamburger [id=" + id + "]"; } public Hamburger(int id) { this.id = id; } } ``` ```java public class Container { public Hamburger[] array = new Hamburger[6]; public int index = 0; //向容器中添加汉堡 public synchronized void push(Hamburger hamburger) { while(index == array.length) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); array[index] = hamburger; index++; System.out.println("生产了一个汉堡:"+hamburger); } //从容器中取出汉堡 public synchronized Hamburger pop() { while(index == 0) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); index--; System.out.println("消费了一个汉堡"+array[index]); return array[index]; } } ``` ```java public class Producer implements Runnable { private Container container = null; public Producer(Container container) { this.container = container; } @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 30; i++) { Hamburger hamburger = new Hamburger(i); this.container.push(hamburger); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ``` ```java public class Consumer implements Runnable { private Container container = null; public Consumer(Container container) { this.container = container; } @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 30; i++) { this.container.pop(); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ``` ```java public class Test5 { public static void main(String[] args) { Container container = new Container(); Producer producer = new Producer(container); Consumer consumer = new Consumer(container); new Thread(producer).start(); new Thread(producer).start(); new Thread(consumer).start(); new Thread(consumer).start(); new Thread(consumer).start(); } } ``` ### 练习 火车站共有3个窗口出售火车票,共15张票,用多线程模拟3个窗口的售票情况。 ```java public class TicketRunnable implements Runnable { //剩余的火车票 public int scount = 15; //已售出的火车票 public int ocount = 0; @Override public void run() { // TODO Auto-generated method stub while(scount>0) { try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(scount == 0) { return; } synchronized (TicketRunnable.class) { scount--; ocount++; if(scount == 0) { System.out.println(Thread.currentThread().getName()+"售出了第"+ocount+"张火车票,火车票已售完"); }else { System.out.println(Thread.currentThread().getName()+"售出了第"+ocount+"张火车票,剩余"+scount+"张火车票"); } } } } } ``` ```java public class Test6 { public static void main(String[] args) { TicketRunnable ticketRunnable = new TicketRunnable(); new Thread(ticketRunnable,"窗口1").start(); new Thread(ticketRunnable,"窗口2").start(); new Thread(ticketRunnable,"窗口3").start(); } } ``` ### 集合框架 集合可以理解为是一个长度可以改变,可以存放任意数据类型的动态数组。 Collection 集合框架最基本的接口,存储一组无序、不唯一的对象 List Collection的子接口,存储一组无序、不唯一的对象 Set Collection的子接口,存储一组无序、唯一的对象 Map 独立于Collection的另外一个接口,存储一组键值对象,提供键到值的映射 Iterator 输出集合元素的接口,一般适用于无序集合,从前向后单向输出 ListIterator Iterator的子接口,可以双向输出集合中的元素 Eummeration 传统的输出接口,已经被Irerator所取代
Account.java
import java.util.concurrent.locks.ReentrantLock; public class Account implements Runnable { private static int num; private ReentrantLock reentrantLock = new ReentrantLock(); @Override public void run() { // TODO Auto-generated method stub reentrantLock.lock(); reentrantLock.lock(); num++; System.out.println(Thread.currentThread().getName()+"是当前的第"+num+"位访问"); reentrantLock.unlock(); reentrantLock.unlock(); } }
Chopsticks.java
public class Chopsticks { }
Consumer.java
public class Consumer implements Runnable { private Container container = null; public Consumer(Container container) { this.container = container; } @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 30; i++) { this.container.pop(); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Container.java
public class Container { public Hamburger[] array = new Hamburger[6]; public int index = 0; //向容器中添加汉堡 public synchronized void push(Hamburger hamburger) { while(index == array.length) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); array[index] = hamburger; index++; System.out.println("生产了一个汉堡:"+hamburger); } //从容器中取出汉堡 public synchronized Hamburger pop() { while(index == 0) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); index--; System.out.println("消费了一个汉堡"+array[index]); return array[index]; } }
DeadLockRunnable.java
public class DeadLockRunnable implements Runnable { public int num; private static Chopsticks chopsticks1 = new Chopsticks(); private static Chopsticks chopsticks2 = new Chopsticks(); @Override public void run() { // TODO Auto-generated method stub if(num == 1) { System.out.println(Thread.currentThread().getName()+"获取到chopsticks1,等待获取chopsticks2"); synchronized (chopsticks1) { try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (chopsticks2) { System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } if(num == 2) { System.out.println(Thread.currentThread().getName()+"获取到chopsticks2,等待获取chopsticks1"); synchronized (chopsticks2) { try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (chopsticks1) { System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } } }
Hamburger.java
public class Hamburger { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Hamburger [id=" + id + "]"; } public Hamburger(int id) { this.id = id; } }
Producer.java
public class Producer implements Runnable { private Container container = null; public Producer(Container container) { this.container = container; } @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 30; i++) { Hamburger hamburger = new Hamburger(i); this.container.push(hamburger); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
StopLock.java
import java.util.concurrent.locks.ReentrantLock; public class StopLock implements Runnable{ private ReentrantLock reentrantLock = new ReentrantLock(); @Override public void run() { // TODO Auto-generated method stub try { reentrantLock.lockInterruptibly(); System.out.println(Thread.currentThread().getName()+"get lock"); Thread.currentThread().sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { reentrantLock.unlock(); } } }
Test.java
public class Test { public static void main(String[] args) { DeadLockRunnable deadLockRunnable1 = new DeadLockRunnable(); deadLockRunnable1.num=1; DeadLockRunnable deadLockRunnable2 = new DeadLockRunnable(); deadLockRunnable2.num=2; Thread thread = new Thread(deadLockRunnable1,"张三"); Thread thread2 = new Thread(deadLockRunnable2,"李四"); thread.start(); try { Thread.currentThread().sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } thread2.start(); } }
Test2.java
public class Test2 { public static void main(String[] args) { Account account = new Account(); Thread thread1 = new Thread(account,"用户A"); Thread thread2 = new Thread(account,"用户B"); thread1.start(); thread2.start(); } }
Test3.java
public class Test3 { public static void main(String[] args) { StopLock stopLock = new StopLock(); Thread thread1 = new Thread(stopLock,"线程1"); Thread thread2 = new Thread(stopLock,"线程2"); thread1.start(); thread2.start(); try { Thread.currentThread().sleep(1000); thread2.interrupt(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Test4.java
public class Test4 { public static void main(String[] args) { TimeLock timeLock = new TimeLock(); new Thread(timeLock,"线程1").start(); new Thread(timeLock,"线程2").start(); } }
Test5.java
public class Test5 { public static void main(String[] args) { Container container = new Container(); Producer producer = new Producer(container); Consumer consumer = new Consumer(container); new Thread(producer).start(); new Thread(producer).start(); new Thread(consumer).start(); new Thread(consumer).start(); new Thread(consumer).start(); } }
Test6.java
public class Test6 { public static void main(String[] args) { TicketRunnable ticketRunnable = new TicketRunnable(); new Thread(ticketRunnable,"窗口1").start(); new Thread(ticketRunnable,"窗口2").start(); new Thread(ticketRunnable,"窗口3").start(); } }
TickerRunnable.java
public class TicketRunnable implements Runnable { //剩余的火车票 public int scount = 15; //已售出的火车票 public int ocount = 0; @Override public void run() { // TODO Auto-generated method stub while(scount>0) { try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(scount == 0) { return; } synchronized (TicketRunnable.class) { scount--; ocount++; if(scount == 0) { System.out.println(Thread.currentThread().getName()+"售出了第"+ocount+"张火车票,火车票已售完"); }else { System.out.println(Thread.currentThread().getName()+"售出了第"+ocount+"张火车票,剩余"+scount+"张火车票"); } } } } }
TimeLock.java
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class TimeLock implements Runnable { public ReentrantLock reentrantLock = new ReentrantLock(); @Override public void run() { // TODO Auto-generated method stub try { if(reentrantLock.tryLock(6, TimeUnit.SECONDS)) { System.out.println(Thread.currentThread().getName()+"get lock"); Thread.currentThread().sleep(5000); }else { System.out.println(Thread.currentThread().getName()+"not lock"); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if(reentrantLock.isHeldByCurrentThread()) { reentrantLock.unlock(); } } } }
原文:https://www.cnblogs.com/HiJackykun/p/11172903.html