Java-多线程(二)

NO.1 单例设计模式
 /**
 * @param args
 * * 单例设计模式:保证类在内存中只有一个对象。
 */
        //单例使用
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s1 == s2);


    }
}

//饿汉式:不管你用不用都创建,有点浪费资源
//class Singleton {
//    //1.私有构造方法,其它类不能访问该构造方法了
//    private  Singleton(){}
//
//    //2.创建本类对象
//    //这里要加个static是因为Singleton方法已经没有办法创建实例变量
//    //将创建的这个s弄成类成员变量,用类名.调用. 其次私有成员变量
//    private static Singleton s = new Singleton();
//
//    //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;
    }

}

/*
 * 饿汉式和懒汉式的区别
 * 1,饿汉式是空间换时间,懒汉式是时间换空间
 * 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象
 */


//第三种写法--了解
class Singleton1 {
    //1,私有构造方法,其他类不能访问该构造方法了
    private Singleton1(){}
    //2,声明一个引用
    public static final Singleton1 s = new Singleton1();

}


NO.2 Runtime类学习
/**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        Runtime r = Runtime.getRuntime();           //获取运行时对象
        //r.exec("shutdown -s -t 300");
        r.exec("shutdown -a");
    }


NO.3 Timer类(掌握)
/**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        Timer t = new Timer();
        //在指定时间安排指定任务
        //第一个参数,是安排的任务,第二个参数是执行的时间,第三个参数是过多长时间再重复执行
        t.schedule(new MyTimerTask(), new Date(188, 6, 1, 14, 22, 50),3000);    
        while(true) {
            Thread.sleep(1000);
            System.out.println(new Date());
        }
    }
}

class MyTimerTask extends TimerTask {
       @Override
    public void run() {
        System.out.println("起床背英语单词");
    }
}

NO.4 两个线程间的通信
/**
     * @param args
     * 等待唤醒机制
     */
    public static void main(String[] args) {
        final Printer p = new Printer();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        
                        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("\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("\r\n");
            flag = 1;
            this.notify();
        }
    }
}

NO.5 三个或者三个以上的线程间通信
/**
     * @param args
     */
    public static void main(String[] args) {
        final Printer2 p = new Printer2();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print3();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}
/*1,在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
 * 2,为什么wait方法和notify方法定义在Object这类中?
 *  因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中
 * 3,sleep方法和wait方法的区别?
 * a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来
 *   wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待
 * b,sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡
 *  wait方法在同步函数或者同步代码块中,释放锁
 */ 
class Printer2 {
    private int flag = 1;
    public void print1() throws InterruptedException {                          
        synchronized(this) {
            while(flag != 1) {
                this.wait();                    //当前线程等待
            }
            System.out.print("黑");
            System.out.print("马");
            System.out.print("程");
            System.out.print("序");
            System.out.print("员");
            System.out.print("\r\n");
            flag = 2;
            //this.notify();                        //随机唤醒单个等待的线程
            this.notifyAll();
        }
    }
    public void print2() throws InterruptedException {
        synchronized(this) {
            while(flag != 2) {
                this.wait();                    //线程2在此等待
            }
            System.out.print("传");
            System.out.print("智");
            System.out.print("播");
            System.out.print("客");
            System.out.print("\r\n");
            flag = 3;
            //this.notify();
            this.notifyAll();
        }
    }
    public void print3() throws InterruptedException {
        synchronized(this) {
            while(flag != 3) {
                this.wait();                        //线程3在此等待,if语句是在哪里等待,就在哪里起来
                                                    //while循环是循环判断,每次都会判断标记
            }
            System.out.print("i");
            System.out.print("t");
            System.out.print("h");
            System.out.print("e");
            System.out.print("i");
            System.out.print("m");
            System.out.print("a");
            System.out.print("\r\n");
            flag = 1;
            //this.notify();
            this.notifyAll();
        }
    }
}

NO.6 互斥锁
/**
     * @param args
     */
    public static void main(String[] args) {
        final Printer3 p = new Printer3();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print3();
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

}

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("员");
            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("i");
            System.out.print("t");
            System.out.print("h");
            System.out.print("e");
            System.out.print("i");
            System.out.print("m");
            System.out.print("a");
            System.out.print("\r\n");
            flag = 1;
            c1.signal();
        r.unlock();
    }
}

NO.7 线程组的概述和使用
//ThreadGroup线程组
        //创建线程-用这个传入Runnable子类对象的方法
        Thread t1 = new Thread(new MyThread(),"Kobe的线程");
        Thread t2 = new Thread(new MyThread(),"奥涅的线程");

        //由线程的getThreadGroup方法获得线程组
        ThreadGroup tg1 = t1.getThreadGroup();
        ThreadGroup tg2 = t2.getThreadGroup();
        //分别打印一下线程组的名字
        System.out.println(tg1.getName());
        System.out.println(tg2.getName());
        //打印结果是main:说明主线程默认就是一个线程组


         //再来自己设置线程组
        MyThread mt = new MyThread();
        ThreadGroup tg = new ThreadGroup("我是一个新的线程组");
        //创建一个线程
        //这个方法的意思是创建一个线程,并加入到tg这个线程组中
        Thread t3 = new Thread(tg,mt,"麦迪");
        Thread t4 = new Thread(tg,mt,"乔丹");
        System.out.println(t3.getThreadGroup().getName());
        System.out.println(t4.getThreadGroup().getName());
       //线程组的作用就是把自己想统一设置的线程放在一起,方便设置

NO.8 多线程的五种状态
123.png
NO.9 线程池的概述和使用
/**
     * public static ExecutorService newFixedThreadPool(int nThreads)
     * public static ExecutorService newSingleThreadExecutor()
     */
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(2);//创建线程池
        pool.submit(new MyRunnable());              //将线程放进池子里并执行
        pool.submit(new MyRunnable());
        pool.shutdown();                            //关闭线程池
    }
}

NO.10 多线程实现方式3 -Callable(了解)
/**
     * @param args
     * @throws ExecutionException 
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool = Executors.newFixedThreadPool(2);//创建线程池
        Future<Integer> f1 = pool.submit(new MyCallable(100));              //将线程放进池子里并执行
        Future<Integer> f2 = pool.submit(new MyCallable(50));
        
        System.out.println(f1.get());
        System.out.println(f2.get());
        pool.shutdown();                            //关闭线程池
    }
}

class MyCallable implements Callable<Integer> {
    private int num;
    public MyCallable(int num) {
        this.num = num;
    }
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for(int i = 1; i <= num; i++) {
            sum += i;
        }
        return sum;
    }
}

NO.11 简单工厂模式的概述和使用
简单工厂模式概述:
 又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
优点:客户端不需要再负责对象的创建,从而明确了各个类的职责
缺点:这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护
//举例:
//1.创建一个Animal的动物类
public abstract class Animal {

   public abstract void eat();//定义一个抽象方法
}
//2.创建一个狗类继承自Animal
public class Dog extends Animal {

   public void eat(){
       System.out.println("狗吃肉");
   }
}
//3.猫类
public class Cat extends Animal {

    public void eat(){
        System.out.println("猫吃鱼");
    }
}
//4.动物工厂
public class AnimalFactory {

 //创建dog对象的类方法
//    public static Dog createDog(){
//        return new Dog();
//    }
////创建猫
//public static Cat createCat(){
//    return new Cat();
//}

//写了以上两个之后,我们就会发现一个问题:如果我们的动物类很多,那么我们就要写很多
    //重复代码,复用性太差
    //改进

    public static Animal createAnimal(String name) {
        //根据传入的名字,来判断需要返回怎样的动物类型
        if ("dog".equals(name)){
            return new Dog();
        }else if("cat".equals(name)){
            return new Cat();
        }else {
            return null;
        }
    }
}
//5.测试类
public class Testjj {

    public static void main(String[] args){

         Dog d = (Dog) AnimalFactory.createAnimal("dog");
         d.eat();

        Cat c = (Cat) AnimalFactory.createAnimal("cat");
        c.eat();
    }
}

NO.12 工厂方法模式
工厂方法模式概述:
工厂方法模式中抽象类工厂类负责定义创建对象的接口,具体对象的创建由继承自抽象工厂类的具体类实现
优点:
客户端不需要再负责对象的创建,从而明确了各个类的职责。如果有新的对象增加,只需要增加一个具体的类和一个具体的工厂类而已。不影响现有代码,后期维护容易,代码可扩展性高

缺点:
需要额外的编写代码,增加了工作量

//案例演示:
//1.创建一个Animal的动物类
public abstract class Animal {
 public abstract void eat();//定义一个抽象方法
}
//2.创建一个狗类继承自Animal
public class Dog extends Animal {

   public void eat(){
       System.out.println("狗吃肉");
   }
}
//3.猫类
public class Cat extends Animal {

    public void eat(){
        System.out.println("猫吃鱼");
    }
}
//4.定义一个工厂接口
public interface Factory {

  public Animal createAnimal();

}
//6.定义一个猫工厂类实现了工厂接口
public class CatFactory implements Factory {
    //重写工厂接口中的方法
    public Animal createAnimal(){

      return new Cat();
    }
}
//7.狗工厂类
public class DogFactory implements Factory {

    public Animal createAnimal(){

        return new Dog();
    }

}
//8.测试类
public class TestTmac {
   public static void main(String[] args){
        Dog d = (Dog) new DogFactory().createAnimal();
        d.eat();
     Cat c = (Cat) new CatFactory().createAnimal();
        c.eat();
    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容