多线程(三)
一、单例设计模式
* 单例设计模式:保证类在内存中只有一个对象。
* 如何保证类在内存中只有一个对象呢?* (1)控制类的创建,不让其他类来创建本类的对象。private
* (2)在本类中定义一个本类的对象。Singleton s;
* (3)提供公共的访问方式。 public static Singleton getInstance(){return s}
* 单例写法两种:
Java Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
* (
1
)饿汉式 //饿汉式 class Singleton { //1,私有构造函数 private Singleton(){} //2,创建本类对象 private static Singleton s = new Singleton(); //3,对外提供公共的访问方法 public static Singleton getInstance() { return s; } public static void print() { System.out.println( "11111111111" ); } } |
Java Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
* (
2
)懒汉式 //懒汉式,单例的延迟加载模式 class Singleton { //1,私有构造函数 private Singleton(){} //2,声明一个本类的引用 private static Singleton s; //3,对外提供公共的访问方法 public static Singleton getInstance() { if (s == null) s = new Singleton(); return s; } public static void print() { System.out.println( "11111111111" ); } } |
二、Timer类,计时器
Java Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public
class
Demo5_Timer { public static void main( String [] args) throws InterruptedException { Timer t = new Timer(); t.schedule( new MyTimerTask(), new Date( 114 , 9 , 15 , 10 , 54 , 20 ), 3000 ); while (true) { System.out.println( new Date()); Thread.sleep( 1000 ); } } } class MyTimerTask extends TimerTask { @Override public void run() { System.out.println( "起床背英语单词" ); } } |
三、线程间通信
1,两个线程之间通信
* 1.什么时候需要通信
* 多个线程并发执行时, 在默认情况下CPU是随机切换线程的
* 如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
* 2.怎么通信
* 如果希望线程等待, 就调用wait()
* 如果希望唤醒等待的线程, 就调用notify();
* 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
2,多个线程之间通信
* 多个线程通信的问题
* notify()方法是随机唤醒一个线程
* notifyAll()方法是唤醒所有线程
* JDK5之前无法唤醒指定的一个线程
* 如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断条件
四、JDK1.5的新特性互斥锁
* 1.同步
* 使用ReentrantLock类的lock()和unlock()方法进行同步
* 2.通信
* 使用ReentrantLock类的newCondition()方法可以获取Condition对象
* 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法
* 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了
Java Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
class
Printer3 { private ReentrantLock r = new ReentrantLock(); private Condition c1 = r.newCondition(); private Condition c2 = r.newCondition(); private Condition c3 = r.newCondition(); private int flag = 1 ; public void print1() throws InterruptedException { r.lock(); //获取锁 if (flag != 1 ) { c1.await(); } System.out.print( "北" ); System.out.print( "京" ); System.out.print( "烤" ); System.out.print( "鸭" ); System.out.print( "\r\n" ); flag = 2 ; //this.notify(); //随机唤醒单个等待的线程 c2.signal(); r.unlock(); //释放锁 } public void print2() throws InterruptedException { r.lock(); if (flag != 2 ) { c2.await(); } System.out.print( "宫" ); System.out.print( "保" ); System.out.print( "鸡" ); System.out.print( "丁" ); System.out.print( "\r\n" ); flag = 3 ; //this.notify(); c3.signal(); r.unlock(); } public void print3() throws InterruptedException { r.lock(); if (flag != 3 ) { c3.await(); } System.out.print( "鱼" ); System.out.print( "香" ); System.out.print( "肉" ); System.out.print( "丝" ); System.out.print( "\r\n" ); flag = 1 ; c1.signal(); r.unlock(); } } |
五、线程的五种状态
* 新建,就绪,运行,阻塞,死亡