2019-06-04 Java学习日记 day25 多线程下

单例设计模式

  保证设计模式:保证类在内存只有一个对象

如何保证泪在内存中只有一个对象

  控制类打的创建,不让其他类来创建本类的对象。private

  在本类重定义一个本类的对象。Singleton s;

  提供公共的访问方法,public static Singleton getInstance(){return s}

 

1.饿汉式 开发用这种方式

2.懒汉式 面试写这种方式

饿汉式是空间换时间,懒汉式是时间换空间

在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象

public class demo1_Singleton {

    public static void main(String[] args) {
        //Singleton s1=new Singleton();  成员变量被私有化,不能直接调用
        //Singleton s1=Singleton.s;
        //Singleton s2=Singleton.s;
        //System.out.println(s1 ==s2);
        
        Singleton s1=Singleton.getInstance();
        Singleton s2=Singleton.getInstance();
        
        System.out.println(s1 == s2);

    }

}
/*//饿汉式
class Singleton{
    //私有构造方法,其他类不能访问该构造方法了
    private Singleton(){}
    //创建类对象
     private  static Singleton s= new Singleton();
     //对外提供公共的访问方法
     public static Singleton getInstance(){ //获取实例
         return s;
     }
}*/

//懒汉式,单例的延迟加载模式
class Singleton{
    //私有构造方法,其他类不能访问该构造方法了
    private Singleton(){}
    //创建类对象
     private  static Singleton s= new Singleton();
     //对外提供公共的访问方法
     public static Singleton getInstance(){ //获取实例
         if (s==null) {
            s =new Singleton();
        }
         return s;
     }
}
案例

多线程(Runtime类)

  *Runtime类是一个单例类

public class demo2_Runtime {

    public static void main(String[] args) throws IOException {
        Runtime r1=Runtime.getRuntime();
        //r1.exec("shutdown -s -t 300");
        r1.exec("shutdown -a");

    }

}
案例

Timer:计时器

year -减 1900 的年份

month - 0-11 之间的月份

date - 一月中1-3 之间的某一天

hrs - 0-23 之间的小时数

min - 0-59 之间的分钟数

sec - 0-59 之间的秒数

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class demo3_Timer {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        Timer t = new Timer();
        //在指定时间安排指定任务
        //第一个参数,是安排的任务,第二个参数是执行的时间,第三个参数是过多长时间再重复执行
        t.schedule(new MyTimerTask(), new Date(119, 5, 5, 0, 30, 10),3000);    
        
        while(true) {
            Thread.sleep(1000);
            System.out.println(new Date());
        }
    }

}

class MyTimerTask extends TimerTask {

    @Override
    public void run() {
        System.out.println("要起床了");
    }
}
案例

两个线程间的通信

  多个线程并发执行时,在默认情况下CPU是随机切换线程的

  如果我们希望他们有规律的执行,就可以使用通信,例如每个线程执行一次打印

怎么通信

  如果希望线程等待,就调用wait()

  如果希望唤醒等待的线程,就调用notify()

  这两个方法必须再同步代码中执行,并且使用同步锁对象来调用

public class demo1_Notify {

    public static void main(String[] args) {
        printer p1=new printer();
        new Thread(){
            public void run(){
                while(true){
                    try {
                        p1.print1();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread(){
            public void run(){
                while(true){
                    try {
                        p1.print2();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }.start();

    }

}
class printer{
    private int flag =1;
    public void print1() throws InterruptedException{
        synchronized (this){
            if (flag !=1) {
                this.wait();  //当前线程等待
            }
        System.out.print("明");
        System.out.print("天");
        System.out.print("是");
        System.out.print("好");
        System.out.print("日");
        System.out.print("子");
        System.out.print("\r\n");
        flag=2;
        this.notify();//随机唤醒单个等待的线程
        
    }
}    
    public void print2() throws InterruptedException{
         synchronized (this){
             if (flag != 2) {
                this.wait();
            }
        System.out.print("今");
        System.out.print("天");
        System.out.print("天");
        System.out.print("气");
        System.out.print("真");
        System.out.print("好");
        System.out.print("\r\n");
        flag =1;
        this.notify();
    }
 }
}
案例

三个或以三个以上间的线程通信

 *多个线程通信的问题

  *notify()方法时随机唤醒一个线程

  *notifyAll()方法时唤醒所有线程

  *JDK5之前无法唤醒指定的一个线程

  *如果多个线程之间通信,需要使用notifyAll()通知所有线程,用while来反复判断条件

jdk1.5的新特性互斥锁

同步

  使用ReentrantLock类的lock()和unlock()方法进行同步

通信

  使用ReentrantLock类的newCondition()方法可以获取Condition对象

  需要等待的时候使用Condition的await()方法,唤醒的时候用signal()方法

  不同的线程使用不同的Condition,这样就能区分唤醒的时候找哪个线程了

  

猜你喜欢

转载自www.cnblogs.com/JungTan0113/p/10973995.html