多线程(创建多线程)

基本概念

  1. 进程:就是执行程序的一次执行过程,它是一个动态的概念,是系统资源分配的单位。就比如,打开电脑的资源管理器可以看到,此时此刻电脑同时运行着多个程序,每个程序有一个独立的进程,而进程之间是相互独立存在的,也就是这些程序同时运行着但是不会相互影响,这就是进程。
  2. 线程:进程想要执行任务就需要依赖线程,就是进程中的最小执行单位就是线程,通常一个进程可以包含若干个线程,并且一个进程中至少有一个线程。
  3. 多线程:多线程顾名思义就是多个线程同时运行,就比如你在使用QQ音乐的时候,你能在听歌的同时,进行搜索歌曲,那么此时这个进程就有了两个线程,即播放音乐和搜索音乐,这就是多线程。

核心知识

  1. 线程就是独立执行的路径。
  2. 在程序运行时,即使自己没有创建线程,后台也会有多个线程,比如主线程、gc线程。
  3. main()称之为主线程,为系统的入口,用于执行整个程序。
  4. 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为的干预的。
  5. 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制。
  6. 线程会带来额外的开销,如cpu调度时间,并发控制开销。
  7. 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。

线程的创建

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

1. Thread class——>继承Thread类
(1) 自定义线程类继承Thread类
(2) 重写run()方法,编写线程执行体
(3) 创建线程对象,调用start()方法启动线程

/*
* 创建线程方式一:
* 继承Thread类——>重新run()方法——>调用start()开启线程
* */

//注意线程开启不一定立即执行,由cpu调度执行
public class TestThread1 extends Thread {
    
    
    @Override
    public void run(){
    
    
        //run方法线程体
        for (int i = 0; i < 10; i++) {
    
    
            System.out.println(i+".播放音乐中");
        }
    }

    public static void main(String[] args) {
    
    
        //main线程,主线程

        //创建一个线程对象
        TestThread1 testThread1=new TestThread1();

        //调用start方法开启线程
        testThread1.start();

        for (int i = 0; i < 100; i++) {
    
    
            System.out.println(i+".搜索歌曲中");
        }
    }
}
//可以看见不是顺序执行的,是两个同时进行的,交互出现
/*部分输出:
47.搜索歌曲中
48.搜索歌曲中
49.搜索歌曲中
0.播放音乐中
1.播放音乐中
2.播放音乐中
3.播放音乐中
4.播放音乐中
5.播放音乐中
6.播放音乐中
7.播放音乐中
8.播放音乐中
9.播放音乐中
50.搜索歌曲中
51.搜索歌曲中
52.搜索歌曲中
53.搜索歌曲中
*/

2. Runnable接口——>实现Runnable接口
(1) 定义MyRunnable类实现Runnable接口
(2) 实现run()方法,编写线程执行体
(3) 创建线程对象,调用start()方法启动线程:(创建实现类对象——创建代理类对象——启动线程)

/*
* 创建线程方式二:
*实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
* */
public class TestThread2 implements Runnable {
    
    
    @Override
    public void run() {
    
    
        for (int i = 0; i < 20; i++) {
    
    
            System.out.println(i+"正在播放歌曲");
        }
    }

    public static void main(String[] args) {
    
    

        //创建实现类对象
        TestThread2 testThread2=new TestThread2();
        //创建代理类对象
        Thread thread=new Thread(testThread2);  //以下两句可写为:new Thread(testThread2).start();
        //启动线程
        thread.start();
        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println(i+"正在搜索歌曲");
        }
    }
}
/*部分输出:
220正在搜索歌曲
221正在搜索歌曲
0正在播放歌曲
222正在搜索歌曲
223正在搜索歌曲
1正在播放歌曲
224正在搜索歌曲
2正在播放歌曲
225正在搜索歌曲
3正在播放歌曲
*/

3. Callable接口——>实现Callable接口
(1) 实现Callable接口,需要返回值类型
(2) 重写call()方法,需要抛出异常
(3) 创建目标对象
(4)创建执行服务:ExecutorService ser= Executors.newFixedThreadPool(1);
(5)提交执行:Futureresult1= ser.submit(t1);
(6)获取结果:boolean r1=result1.get();
(7)关闭服务:ser.shutdownNow();

//线程创建方式三:实现callable接口
/*Callable的好处
1. 可以定义返回值
2. 可以抛出异常
* */
public class TestThread4 implements Callable<Boolean> {
    
    
    @Override
    public Boolean call() throws Exception {
    
    
        for (int i = 0; i < 5; i++) {
    
    
            System.out.println(i+"正在播放歌曲");
        }
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    

        //创建实现类对象
        TestThread4 testThread4=new TestThread4();
        //创建执行服务
        ExecutorService ser= Executors.newFixedThreadPool(2);
        //提交执行
        Future<Boolean> r1= ser.submit(testThread4);
        //获取结果
        boolean rs1=r1.get();
        //关闭服务
        ser.shutdownNow();
    }
}
/*输出:
0正在播放歌曲
1正在播放歌曲
2正在播放歌曲
3正在播放歌曲
4正在播放歌曲

Process finished with exit code 0
*/

并发问题:模拟一个买火车票,通过输出可以发现,多个线程操作同一个资源的情况下,线程不安全,数据紊乱,同一张票被多人拿到。

//多个线程操作同一个对象
public class TestThread3 implements Runnable{
    
    

    private int tickenum=10;
    @Override
    public void run() {
    
    
         while (true){
    
    
             if(tickenum<=0) {
    
    
                 break;
             }
             //模拟一个延时
             try {
    
    
                 Thread.sleep(100);
             } catch (InterruptedException e) {
    
    
                 e.printStackTrace();
             }
             //Thread.currentThread().getName()获取当前执行进程的名字
             System.out.println(Thread.currentThread().getName()+"拿到了第"+tickenum--+"张票");
         }
    }

    public static void main(String[] args) {
    
    
        TestThread3 testThread3=new TestThread3();

        new Thread(testThread3,"小明").start();
        new Thread(testThread3,"小王").start();
        new Thread(testThread3,"小张").start();
    }
}
/*输出:
小明拿到了第9张票
小王拿到了第10张票
小张拿到了第10张票
小明拿到了第8张票
小王拿到了第7张票
小张拿到了第6张票
小明拿到了第5张票
小张拿到了第4张票
小王拿到了第3张票
小明拿到了第2张票
小张拿到了第1张票
小王拿到了第1张票
小明拿到了第0张票

Process finished with exit code 0
*/

模拟龟兔赛跑

//模拟龟兔赛跑
public class Race implements Runnable {
    
    

    //胜利者
    private static String winner;
    @Override
    public void run() {
    
    
        for (int i = 0; i <=100; i++) {
    
    

            //如果是兔子就休息
            if(Thread.currentThread().getName()=="兔子"&&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("winner is "+winner);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
    
    
        Race race=new Race();
        new Thread(race,"乌龟").start();
        new Thread(race,"兔子").start();
    }
}
/*部分输出:
兔子——>跑了——>6步
兔子——>跑了——>7步
兔子——>跑了——>8步
兔子——>跑了——>9步
乌龟——>跑了——>91步
乌龟——>跑了——>92步
乌龟——>跑了——>93步
乌龟——>跑了——>94步
乌龟——>跑了——>95步
乌龟——>跑了——>96步
乌龟——>跑了——>97步
乌龟——>跑了——>98步
乌龟——>跑了——>99步
winner is 乌龟
*/

猜你喜欢

转载自blog.csdn.net/z3447643805/article/details/113753599