美文网首页
Java-多线程(二)

Java-多线程(二)

作者: 浮桥小麦 | 来源:发表于2017-06-24 10:14 被阅读7次
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();
    }

}

相关文章

  • Java-多线程(二)

    NO.1 单例设计模式 NO.2 Runtime类学习 NO.3 Timer类(掌握) NO.4 两个线程间的通...

  • JAVA-线程-一-执行器Executor

    2. JAVA-线程-二-ExecutorService 接口 3. JAVA-线程-三-AbstractExec...

  • JAVA-线程-三-AbstractExecutorServic

    1. JAVA-线程-一-执行器Executor 2. JAVA-线程-二-ExecutorService 接口 ...

  • Java-多线程详解(二)

    线程的同步 1.线程同步问题的引出 下面模拟一个简单的卖票程序,两个线程,卖10张票 运行结果: 这时我们发现,操...

  • Hello Java

    目录 Java-基础(1/6) Java-对象(2/6) Java-核心库类 上(3/6) Java-核心库类下(...

  • java-多线程

    介绍一下Syncronized锁。如果用这个关键字修饰一个静态方法,锁住了什么?如果修饰成员方法,锁住了什么? 修...

  • java-多线程

    多线程 synchronized 1、synchronized关键字 简介解决多个线程之间访问资源的同步性。保证被...

  • Java-浅析Object类

    Java-浅析Object类 ++2016.7.19++byside @Java-浅析Object类 ======...

  • Java-多线程(一)

    NO.1 多线程简介 NO.2 多线程实现方式(一) NO.3 多线程实现方式(二) NO.4 匿名内部类实现线程...

  • Java-多线程编程

    前言: Java的多线程编程随着应用功能越来越复杂,用户对软件体验要求越来越高,那么对于多线程的编程越发重要了。接...

网友评论

      本文标题:Java-多线程(二)

      本文链接:https://www.haomeiwen.com/subject/jvvfcxtx.html