Java 多线程(二)线程创建

三种创建方式

1.继承Thread类

2.实现Runnable接口

3.实现Callable接口(了解)

 

继承Thread类

自定义线程继承Thread类

重写run()方法,编写线程执行体

创建线程对象,调用start()方法启动线程

  

可以看到,他们是交替执行的,具体执行顺序看cpu调度,每次调度情况也不会相同

线程开启不一定立即执行,由cpu调度执行

//创建线程方式一
public class TestThread1 extends Thread{
    @Override
    public void run() {
        //run()方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码--"+i);
        }
    }

    //main主线程
    public static void main(String[] args) {
        //创建线程对象
        TestThread1 testThread1 = new TestThread1();
        //调用start()方法开启线程
        testThread1.start();

        for (int i = 0; i < 200; i++) {
            System.out.println("我在学习多线程"+i);
        }
    }
}

 

实现Runnable接口

定义MyRunnable类实现Runnable接口

实现run()方法,编写线程执行体

创建线程对象,调用start()方法启动线程

//创建线程方式二
public class TestThread2 implements Runnable{
    @Override
    public void run() {
        //run()方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码--"+i);
        }
    }

    //main主线程
    public static void main(String[] args) {
        //创建Runnable接口对象实现类对象
        TestThread2 testThread2 = new TestThread2();
        //创建线程对象,通过线程对象开启线程
//        Thread thread = new Thread(testThread2);
//        thread.start();
        new Thread(testThread2).start();

        for (int i = 0; i < 200; i++) {
            System.out.println("我在学习多线程"+i);
        }
    }
}

下面举一个具体的例子,多个线程同时操作一个对象,并初识并发问题,以买火车票为例

public class TestThread3 implements Runnable{
    //火车票票数
    private int ticketNum = 10;
    @Override
    public void run() {
        while(true) {
            if (ticketNum <= 0) {
                break;
            }
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "-->拿到了第" + ticketNum-- + "票");
            }
        }

    public static void main(String[] args) {
        TestThread3 testThread3 = new TestThread3();
        new Thread(testThread3,"小明").start();
        new Thread(testThread3,"小红").start();
        new Thread(testThread3,"小强").start();
        new Thread(testThread3,"小黄").start();
    }
}

  可以看到,多个人都拿到了同一张票。我们发现多个线程操作一个资源的情况下,线程不安全,数据紊乱

 

我们再写一个具体的例子,龟兔赛跑。

public class Race implements Runnable{
    //胜利者
    private static String winner;
    @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(winner +"赢了");
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

 

实现Callable接口

1.实现Callable接口,需要返回值类型

2.重写call方法,需要抛出异常

3.创建目标对象

4.创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1)

5.提交执行:Future<Boolean> result1 = ser.submit(t1)

6.获取结果:boolean r1 = result1.get()

7.关闭服务:ser.shutdownNow()

 

小结

  继承Thread类:

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

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

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

 

  实现Runnable接口:

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

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

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

posted on 2022-10-09 10:49  键盘敲烂的朱  阅读(34)  评论(0编辑  收藏  举报