多线程( 单列设计模式 :* 掌握)
单例设计模式 :保证类在内存中只有一个对象。
饿汉式和懒汉式的区别:
* 1. 饿汉式时空间换时间;懒汉式是时间换空间 。(不推荐懒汉式的使用)
* 2. 在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象 。
单列的三种写法:
/* * 饿汉式 */ class Singleton{ //1.私有构造方法,其他类不能访问该类构造方法 private Singleton () {}; //2.创建本类对象 private static Singleton s=new Singleton(); //成员变量Singleton s 被私有,不能通过类名 . 调用 //3.对外提供公共的访问方法 public static Singleton getInstance() { //获取实例 return s; } } /* * 懒汉式 :单例延迟加载模式(单列模式不用的,因为有可能创建多个对象) */ class Singleton{ //1.私有构造方法,其他类不能访问该类构造方法 private Singleton () {}; //2.声明一个引用 private static Singleton s; //3.对外提供公共的访问方法 public static Singleton getInstance() { //获取实例 if(s==null){ s=new Singleton(); } return s; } } /* * 第三种 */ class Singleton{ //1.私有构造方法,其他类不能访问该类构造方法 private Singleton () {}; //2.创建本类对象 public static final Singleton s=new Singleton(); // 添加final后不会被改变 s }
多线程( Runtime类)
Runtime类是一个单例类。
public static void main(String[] args) throws IOException { // 操作同一个对象 shutdown Runtime r= Runtime.getRuntime(); //获取运行时对象 r.exec("shutdown -s -t 300"); // 修改了 r.exec("shutdown -a"); // 根据上一个对象去修改 }
多线程( Timer类 :* 掌握)
Timer类 :计时器。
public class Dome3_Timer { public static void main(String[] args) throws InterruptedException { Timer t=new Timer(); //创建一个计时器 //schedule():在指定时间安排指定任务。 //第一个参数是指定任务,第二个参数是执行的时间,第三个参数是过多长时间再重复执行 t.schedule(new MyTimer(),new Date(119, 5, 6, 0, 57, 4 0),2000); while (true) { Thread.sleep(1000); System.out.println(new Date()); } } } class MyTimer extends TimerTask{ @Override public void run() { System.out.println("起来读书"); } }
多线程( 两个线程间的通信:* 掌握)
1.什么时候需要通信:
* 多个线程并发执行时,在默认情况下CPU时随机切换线程的。
* 如果我们希望他们有规律的执行,就可以使用通讯 。
2.怎么通信:
* wait():当前线程等待
* notify():随机唤醒单个等待的线程
* 这两个方法必须在同步代码中执行,并且使用同步锁对象来调用。
public class Dome1_Notify { public static void main(String[] args) { final Printer p=new Printer(); new Thread() { public void run () { while(true) { try { p.print1(); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } }.start(); new Thread() { public void run () { while(true) { try { p.print2(); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } }.start(); } } //等待唤醒机制 class Printer{ private int flag=1; public void print1() throws InterruptedException { synchronized (this) { if (flag!=1) { this.wait(); } System.out.print("a"); System.out.print("b"); System.out.print("c"); System.out.print("\r\n"); flag=2; this.notify(); //随机唤醒单个等待的线程 } } public void print2() throws InterruptedException { synchronized (this) { if (flag!=2) { this.wait(); //this.wait():当前线程等待 } System.out.print("d"); System.out.print("e"); System.out.print("f"); System.out.print("\r\n"); flag=1; this.notify(); //this.notify():随机唤醒单个等待的线程 } } }
多线程( 线程间的通信注意问题)
1. 在同步代码块中,用那个对象锁,就用哪个对象调用wait 方法。
2. 因为锁对象是可以任意对象,Object是所有的类的基类,所以wait( ) 和notify( )需要定义在Object这个类中。
3.sleep方法和wait方法的区别
( 1 ) * sleep方法必须传入参数,参数就是时间,时间到了就自动醒来。
* wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待。
( 2 ) * sleep方法在同步函数或同步代码块中,不是放锁。
* wait方法在同步函数或者同步代码块中,释放锁。
多线程( JDK1.5的新特性互斥锁:*掌握)
1.同步:
*使用ReentrantLock的 lock( ) 和 unlock( )方法进行听不。
2. 通信:
* 使用ReentrantLock类的newCondition( )方法可以获取Condition对象。
* 需要等待的时候使用Condition的await ( ) 方法,唤醒的时候用signal( )方法。
* 不用的线程使用不同的Condition,这样就能区分唤醒的时候找到那个线程了。
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(); //lock():获取锁 if (flag != 1) { c1.await(); } System.out.print("a"); System.out.print("b"); System.out.print("c"); System.out.print("\r\n"); flag = 2; c2.signal(); //signal():释放锁 } public void print2() throws InterruptedException { r.lock(); if (flag != 2) { c2.await(); } System.out.print("e"); System.out.print("f"); System.out.print("g"); System.out.print("\r\n"); flag = 3; c3.signal(); } public void print3() throws InterruptedException { r.lock(); if (flag != 3) { c3.await(); } System.out.print("h"); System.out.print("i"); System.out.print("j"); System.out.print("\r\n"); flag = 1; c1.signal(); } }