0
点赞
收藏
分享

微信扫一扫

并发谈nv朋友(多线程详解)

陈情雅雅 2022-04-06 阅读 56
java

并发谈nv朋友(多线程详解)

Process 、Thread

  1. 继承 Thread 类
  2. 实现Runnable 接口
  3. 实现Callable接口

继承 Thread 类

子类继承Thread 类具备多线程能力

启动线程:子类对象.start();

不建议使用:避免OOP单继承局限性

实现Runnable 接口

实现接口Runnable具备多线程能力

启动线程:传入目标对象+Thread对象.start();

推荐使用:避免单继承局限性、灵活方便,方便同一对象被多个线程使用

并发问题

龟兔赛跑

package thread;

//模拟龟兔赛跑
public class Rabbitgame implements Runnable {
    //胜利者
    private static String winner;
    public static void main(String[] args) {
        Rabbitgame race = new Rabbitgame();
        new Thread(race, "兔子").start();
        new Thread(race, "乌龟").start();
    }
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            //模拟兔子休息
            if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //判断比赛是否已经结束
            boolean flag = gameover(i);
            //如果比赛结束,就终止程序
            if (flag) {
                break;
            }
            System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "步");
        }
    }
    //判断是否完成比赛
    private boolean gameover(int steps) {
        //判断是否有胜利者
        if (winner != null) {//已经存在胜利者
            return true;
        }
        {
            if (steps >= 100) {
                winner = Thread.currentThread().getName();
                System.out.println("winer is" + winner);
                return true;
            }
        }
        return false;
    }
}
/*
兔子-->跑了0步
乌龟-->跑了0步
兔子-->跑了1步
乌龟-->跑了1步
兔子-->跑了2步
乌龟-->跑了2步
兔子-->跑了3步
兔子-->跑了4步
兔子-->跑了5步
兔子-->跑了6步
兔子-->跑了7步
兔子-->跑了8步
兔子-->跑了9步
乌龟-->跑了3步
乌龟-->跑了4步
乌龟-->跑了5步
乌龟-->跑了6步
乌龟-->跑了7步
乌龟-->跑了8步
乌龟-->跑了9步
乌龟-->跑了10步
乌龟-->跑了11步
乌龟-->跑了12步
乌龟-->跑了13步
乌龟-->跑了14步
乌龟-->跑了15步
乌龟-->跑了16步
乌龟-->跑了17步
乌龟-->跑了18步
乌龟-->跑了19步
乌龟-->跑了20步
乌龟-->跑了21步
乌龟-->跑了22步
乌龟-->跑了23步
乌龟-->跑了24步
乌龟-->跑了25步
乌龟-->跑了26步
乌龟-->跑了27步
乌龟-->跑了28步
乌龟-->跑了29步
乌龟-->跑了30步
乌龟-->跑了31步
乌龟-->跑了32步
乌龟-->跑了33步
乌龟-->跑了34步
乌龟-->跑了35步
乌龟-->跑了36步
乌龟-->跑了37步
乌龟-->跑了38步
乌龟-->跑了39步
乌龟-->跑了40步
乌龟-->跑了41步
乌龟-->跑了42步
乌龟-->跑了43步
乌龟-->跑了44步
乌龟-->跑了45步
乌龟-->跑了46步
乌龟-->跑了47步
乌龟-->跑了48步
乌龟-->跑了49步
乌龟-->跑了50步
乌龟-->跑了51步
乌龟-->跑了52步
乌龟-->跑了53步
乌龟-->跑了54步
乌龟-->跑了55步
乌龟-->跑了56步
乌龟-->跑了57步
乌龟-->跑了58步
乌龟-->跑了59步
乌龟-->跑了60步
乌龟-->跑了61步
乌龟-->跑了62步
乌龟-->跑了63步
乌龟-->跑了64步
乌龟-->跑了65步
乌龟-->跑了66步
乌龟-->跑了67步
乌龟-->跑了68步
乌龟-->跑了69步
乌龟-->跑了70步
乌龟-->跑了71步
乌龟-->跑了72步
乌龟-->跑了73步
乌龟-->跑了74步
乌龟-->跑了75步
乌龟-->跑了76步
乌龟-->跑了77步
乌龟-->跑了78步
乌龟-->跑了79步
乌龟-->跑了80步
乌龟-->跑了81步
乌龟-->跑了82步
乌龟-->跑了83步
乌龟-->跑了84步
乌龟-->跑了85步
乌龟-->跑了86步
乌龟-->跑了87步
乌龟-->跑了88步
乌龟-->跑了89步
乌龟-->跑了90步
乌龟-->跑了91步
乌龟-->跑了92步
乌龟-->跑了93步
乌龟-->跑了94步
乌龟-->跑了95步
乌龟-->跑了96步
乌龟-->跑了97步
乌龟-->跑了98步
乌龟-->跑了99步
winer is乌龟
* */

实现Callable接口

step1:创建一个Callable接口的实现类,需要返回值类型
step2:重写call方法,需要抛出异常
step3:创建目标对象
step4:创建执行服务
step5:提交执行
step6:获取结果
step7:关闭服务

import java.util.concurrent.*;//JUC并发编程包
public class CallableTest implements Callable<Boolean> {
    @Override
    public Boolean call() throws Exception {
        System.out.println("线程"+Thread.currentThread().getName()+"执行了");
        return true;
    }
    public static void main(String[] args) {
        CallableTest c1 = new CallableTest();
        CallableTest c2 = new CallableTest();
        //创建线程池执行服务,传入线程数
        /*
        newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池,
        以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。
        如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。
        如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。
        在某个线程被显式地关闭之前,池中的线程将一直存在。
         */
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        //提交执行
        //Future 表示异步计算的结果。
        // 它提供了检查计算是否完成的方法,以等待计算的完成,
        // 并获取计算的结果。计算完成后只能使用 get 方法来获取结果
        Future<Boolean> result1 = executorService.submit(c1);
        Future<Boolean> result2 = executorService.submit(c2);
        //获取结果
        try {
            Boolean resultA = result1.get();
            Boolean resultB = result2.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally {
            //在finally中关闭服务可以最大程度保证线程池的安全
            executorService.shutdownNow();
        }
    }
}

静态代理模式

静态代理模式:StaticProxy

代理对象和真是对象都要实现同一个接口
代理对象要代理真是角色

注意的是,静态代理的函数,随着传入参数不同,目标对象也就会调用不同的参数

/*
婚庆公司就是Thread
静态代理模式:StaticProxy
代理对象和真是对象都要实现同一个接口
代理对象要代理真是角色
 */
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();
        My my = new My();
        WedCompany wedCompany = new WedCompany(you);
        WedCompany wedCompany2 = new WedCompany(my);
        wedCompany.HappyMarry();
        wedCompany2.HappyMarry();
    }
}
//结婚接口
interface Marry{
    public void HappyMarry();
}
//真是角色,你去结婚
class You implements Marry{
    @Override
    public void HappyMarry() {
        System.out.println("我要结婚了,我很高兴!!!");
    }
}
class My implements Marry{
    @Override
    public void HappyMarry() {
        System.out.println("结婚的不是我,哭死!!!");
    }
}
//婚庆公司,婚庆公司代理你把一些事情
class WedCompany implements Marry{
    private Marry target;//结婚客户
    @Override
    public void HappyMarry() {
        System.out.println("结婚之前,布置现场");
        //这个就是真是对象,随着传入的参数不同,target不同调用不同对象的HappyMarry()
        this.target.HappyMarry();
        System.out.println("结婚之后,守尾款");
    }
    public WedCompany(Marry target) {
        this.target = target;
    }
}
举报

相关推荐

0 条评论