java多线程(下)

1.单例设计模式

public class Demo1_Singleton {
    /*
        单例设计模式:保证类在内存中只有一个对象
     */
    public static void main(String[] args) {
//        Singleton s=Singleton.s;     成员变量被私有,不能通过类名.调用

        Singleton s1=Singleton.getIntance();
        Singleton s2=Singleton.getIntance();
        System.out.println(s1==s2);

    }
}

///*
//    方式一:饿汉式(开发时用)
// */
class Singleton{

   //1.私有构造方法
   private Singleton(){}
    //2.创建实例对象
   private static Singleton s=new Singleton();
   //3.对外公开可调用的方法
   public static Singleton getIntance(){
       return s;
   }
}

	
/*
    方式二:懒汉式,(单例的延迟加载模式)(面试时用)
 */
class Singleton{

    //1.私有构造方法
    private Singleton(){}
    //2.创建实例对象
    private static Singleton s;
    //3.对外公开可调用的方法
    public static Singleton getIntance(){
        if (s==null){
            //线程1等待,线程2等待(可能创建多个对象)
            s=new Singleton();
        }
        return s;
    }
}

饿汉式和懒汉式的区别:

1.饿汉式是空间换时间。懒汉式是时间换空间

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

Runtime类

用了单例设计模式

Runtime r=Runtime.getRuntime();
r.exec("shutdown -s -t 300");//执行cmd命令
r.exec("shutdown -a");

2.Timer定时器类

timer定时器类,就是用线程实现的。以下代码为timer定时器类使用方法。

public class Demo3_TimerTask {
    public static void main(String[] args) {
        //Timer创建对象
        Timer timer=new Timer();
        //开启定时器,延时1000毫秒开始,每2000毫秒调用一次MyTimerTask()对象。
        timer.schedule(new MyTimerTask(),1000,2000);
    }
}

class MyTimerTask extends TimerTask{

    @Override
    public void run() {
        //获取当前时间
        Date data=new Date(System.currentTimeMillis());
        //将时间格式化
        SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
        System.out.println(format.format(data));

    }
}

3.线程之间的通信

1.什么时候需要通信

* 多个线程并发执行的时候,在默认情况下CPU是随机切换线程的。
* 若我们希望他们有规律的执行,就可以使用通信。

2.怎么通信

* 如果希望线程等待,就调用wait();
* 如果希望唤醒等待的线程,就调用notify();
* 这两个方法必须在同步代码中执行,并使用同步锁对象来调用。

三个以上线程之间的通讯

  • notify()方法是随机唤醒一个线程
  • notifyAll()方法是唤醒所有线程
  • JDK5之前是无法唤醒指定线程的
  • 如果多个线程之间进行通信,需要使用notifyAll()方法是唤醒所有线程,用while来反复进行判断条件。
public class Demo1_Notify {
    public static void main(String[] args) {
        Printer p=new Printer();
		
        //线程一
        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        
		//线程二
        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        p.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}


class Printer{

    private int flag=1;
    public void print1() throws InterruptedException {
        synchronized (this){
            while (flag!=1){   //while是循环判断,每次都会判断标记。
                this.wait();   //当前线程等待
            }
            System.out.print("1");
            System.out.print("2");
            System.out.print("3");
            System.out.print("4");
            System.out.print("5");
            System.out.print("6");
            System.out.print("7");
            System.out.print("8");
            System.out.println();
            flag=2;
            //this.notify();  //随机唤醒单个等待线程。
            this.notifyAll(); //唤醒所有线程
        }
    }

    public void print2() throws InterruptedException {
        synchronized (this){
            while (flag!=2){
                this.wait();
            }
            System.out.print("湖");
            System.out.print("北");
            System.out.println();
            flag=3;
            //this.notify();
            this.notifyAll(); //唤醒所有线程
        }
    }

    public void print3() throws InterruptedException {
        synchronized (this){
            while (flag!=3){
                this.wait();
            }
            System.out.print("hhhh");
            System.out.print("bbbb");
            System.out.println();
            flag=1;
            //this.notify();
            this.notifyAll(); //唤醒所有线程
        }
    }
}

4.JDK1.5特性互斥锁

1.同步

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

2.通信

  • 使用ReentrantLock类的newCondition()方法可以获取Condition对象
  • 需要等待的时候使用newCondition的await()方法,唤醒的时候使用signal()方法
  • 不同的线程使用不同的condition,这样就能精准唤醒指定线程

public class Demo2_ReentrantLock {
    public static void main(String[] args) {
        Printer2 p=new Printer2();

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        p.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}
//等待唤醒机制
class Printer2{

    private int flag=1;
    private ReentrantLock r=new ReentrantLock();
    private Condition c1=r.newCondition();//获取线程对象
    private Condition c2=r.newCondition();
    private Condition c3=r.newCondition();

    public void print1() throws InterruptedException {


            r.lock();
            if (flag!=1){   //while是循环判断,每次都会判断标记。
                c1.await();//线程休眠
            }
            System.out.print("1");
            System.out.print("2");
            System.out.print("3");
            System.out.print("4");
            System.out.print("5");
            System.out.print("6");
            System.out.print("7");
            System.out.print("8");
            System.out.println();
            System.out.println();
            flag=2;
            //this.notify();  //随机唤醒单个等待线程。
            c2.signal();//唤醒c2对象的线程
        r.unlock();
    }

    public void print2() throws InterruptedException {
        r.lock();
        if (flag!=2){
               c2.await();
            }
            System.out.print("湖");
            System.out.print("北");
            System.out.println();
            flag=3;
            //this.notify();
           c3.signal();
        r.unlock();
    }

    public void print3() throws InterruptedException {
        r.lock();
            if (flag!=3){
               c3.await();
            }
            System.out.print("hhhh");
            System.out.print("bbbb");
            System.out.println();
            flag=1;
            //this.notify();
            c1.signal();
        r.unlock();
    }
}

5.静态代理

静态代理模式:

要求代理类和被代理类使用同一个接口,重写其中的方法,代理类重写的方法实际上调用的是被代理类重写的方法。

测试代码:

package Agency.StaticDemo;

public interface Animal {

    //叫声
    public void cry();

    //吃
    public void eat();
}

被代理类:Cat

package Agency.StaticDemo;

public class Cat implements Animal{

    @Override
    public void cry() {
        System.out.println("喵喵");
    }

    @Override
    public void eat() {
        System.out.println("吃鱼");
    }
}

代理类:CatAgency

package Agency.StaticDemo;

public class CatAgency implements Animal{
    //Cat是被代理的类,CatAgency是代理Cat的类
    Cat cat;

    public CatAgency(Cat cat){
        this.cat=cat;
    }

    @Override
    public void cry() {
        System.out.println("CatAgency代理开始");
        cat.cry();
        System.out.println("CatAgency代理结束");
    }

    @Override
    public void eat() {
        System.out.println("CatAgency代理开始");
        cat.eat();
        System.out.println("CatAgency代理结束");
    }

    public static void main(String[] args) {

        Cat cat=new Cat();
        CatAgency catAgency=new CatAgency(cat);
        catAgency.cry();
        catAgency.eat();
    }


}

执行结果:

image-20220403101822952

6.动态代理

静态代理每代理一个对象,就要创建一个代理对象,很浪费空间。动态代理就解决了这个问题。

动态代理:当需要通过代理类来调用其它对象的方法,程序运行的时候可以动态的创建目标类的代理对象。

测试代码:

接口类

package Agency.ActiveDemo;

public interface Animal {

    //叫声
    public void cry();

    //吃
    public void eat();
}

实现接口类

package Agency.ActiveDemo;

public class Cat implements Animal {

    @Override
    public void cry() {
        System.out.println("喵喵");
    }

    @Override
    public void eat() {
        System.out.println("吃鱼");
    }
}

实现InvocationHandler接口的动态代理类

package Agency.ActiveDemo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyProxy implements InvocationHandler {

    private Object object;

    public MyProxy(Object object){
        this.object=object;
    }


    //method是对象执行的方法
    //方法参数args
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("==============代理类开始执行!!!!=============");
        //returnVal是方法的返回值
        Object returnVal = method.invoke(object, args);
        System.out.println("==============代理类执行结束!!!!=============");
        return returnVal;
    }
}

Main方法执行类

package Agency.ActiveDemo;

import java.lang.reflect.Proxy;

public class RunMain {
    public static void main(String[] args) {
        Cat cat=new Cat();
        //创建动态代理
        //1.执行invoke方法,获取对象的方法
        MyProxy myProxy=new MyProxy(cat);
        //2.实质上是通过反射将 被代理类的加载器 和 接口 与 代理对象 关联起来
        Animal animal= (Animal) Proxy.newProxyInstance(
                cat.getClass().getClassLoader(),//被代理对象的类加载器
                cat.getClass().getInterfaces(),//被代理对象的接口
                myProxy);//实现InvocationHandler接口的方法

        animal.cry();
        animal.eat();


    }
}

推广一哈

大家如果有云存储的需求可以上九牛云存储https://s.qiniu.com/immAni,免费领取10G的存储空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值