创建线程

创建线程我们要通过Thread类来实现,一共有下述5种创建方式

继承 Thread, 重写 run

//先创建一个自己的Thread类,继承自Thread类
class MyThread extends Thread {
    //这里重写run()方法
    @Override
    public void run() {
        while (true) {
            System.out.println("Hello Thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo1 {

    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread();
        t.start();                    //记得在main里面启动线程喔
        while (true) {
            System.out.println("Hello main");
            Thread.sleep(1000);
        }
    }
}

结果如下所示

以下几种创建方式将不再展示结果,因为结果相同,只是创建的方式不同~~

实现 Runnable, 重写 run

//创建自己的Thread类,接入Runnable接口
class MyRunnable implements Runnable {
    //重写run()方法
    @Override
    public void run() {
        while (true) {
            System.out.println("Hello Thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new MyRunnable());
        t.start();
        while (true) {
            System.out.println("Hello main");
            Thread.sleep(1000);
        }
    }
}

继承 Thread, 重写 run, 使用匿名内部类

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        //直接在创建时使用匿名内部类
        Thread t = new Thread() {
            //还是要重写run()方法
            @Override
            public void run() {
                while (true) {
                    System.out.println("Hello Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t.start();
        while (true) {
            System.out.println("Hello main");
            Thread.sleep(1000);
        }
    }
}

实现 Runnable, 重写 run, 使用匿名内部类

public class Demo4 {
    public static void main(String[] args) throws InterruptedException {
        //创建时用Runnable的匿名内部类
        Thread t = new Thread(new Runnable() {
            //还是要重写run()方法
            @Override
            public void run() {
                while (true) {
                    System.out.println("Hello Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();
        while (true) {
            System.out.println("Hello main");
            Thread.sleep(1000);
        }
    }
}

使用 lambda 表达式

最推荐的方式,并且不用重写run()方法

public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        //使用lambda表达式,不用重写run()方法
        Thread t = new Thread(() -> {
            while (true) {
                System.out.println("Hello Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        while (true) {
            System.out.println("Hello main");
            Thread.sleep(1000);
        }
    }
}

启动线程:start()方法和run()方法的区别

通过上述创建过程,我们可以发现,要实现线程的创建和运行,需要start()方法和run()方法的共同协作,那么也许大家会有疑问,这两个方法到底有什么区别呢,可以混用吗?

所以在这里,我们简单地为大家介绍一下

从方法性质上说

  1. 从方法性质上来说,我们在创建过程中可以发现,run()方法是在普通方法,需要被重写使用;run()方法是会在线程启动时被直接调用的,是被动被执行的
  2. start()方法则是Thread类中特有的方法,调用这个方法是主动执行的

从结果上来说

  1. 如果直接执行run()方法就和执行一个普通方法一样,是按顺序执行的,并不能启动一个新的线程
  2. 如果执行start()方法,就是启动一个新的线程~~运行过程是会和main()方法并发执行的多线程

大家在使用的时候一定不要用错了!!~~

中断线程

这里我们讨论的主要是如何去中断线程,一般有以下两种情况

通过共享的标记来沟通

场景提示

我们在用代码展示之前,先设置一个场景,假设你受老板之托帮助公司转账,但是后面老板发现,对面好像是个骗子,于是你和老板约定好了一个变量 isQuit[可以看作是手机],如果老板发现对面是骗子,那么就会把这个变量变成true,然后告诉你,你收到消息也马上停止转账;反之,如果是false,你就继续转账

public class Demo12 {
    public static volatile boolean isQuit = false;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("你正在转账");
           while (!isQuit) {
               try {
                   Thread.sleep(3000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
            System.out.println("你停止了转账");
        });

        System.out.println("老板喊你开始转账");
        t1.start();
        Thread.sleep(2000);
        System.out.println("老板发现对方是骗子,打电话通知你");
        isQuit = true;    //这里置为true可以理解为老板打电话的过程
    }
}

使用interrupt()方法来通知

同样的场景,我们用interrupt()来实现

public class Demo13 {
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                System.out.println("你正在转账");
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
                System.out.println("你停止了转账");
            });

            System.out.println("老板喊你开始转账");
            t1.start();
            Thread.sleep(4000);
            System.out.println("老板发现对方是骗子,打电话通知你");
            t1.interrupt();            //用interrupt()方法实现打电话
        }
}

等待线程

有的时候,我们有的线程需要等待其它线程做完工作之后,才开始被执行,这个时候,我们称它需要等待其它线程,而要实现这样的功能,就需要用到join()方法,老规矩,我们还是上情景~~

场景

Tina觉得最近太热了,想开空调,发现没电费了,于是Tina要先充电费才能开空调,即开空调这个线程应该等待充电费这个线程

public class Demo14 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("充值电费");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("电费充值完毕");
        });

        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("打开空调");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("空调已开启~~Tina感觉很凉快 :) ");
        });

        System.out.println("Tina想开空调,发现没电了!!");
        Thread.sleep(3000);
        System.out.println("Tina先充了电费");
        t1.start();
        t1.join();      //空调要等电费充完才能打开

        Thread.sleep(2000);
        System.out.println("太好了!!电费充好了~~Tina打开了空调");
        t2.start();
    }
}

休眠线程

其实关于线程的休眠,我们前面已经多次使用过了,就是Thread.sleep()方法,单位是毫秒,使用之后,线程就会进入休眠状态,值得注意的是,它的使用必须要处理异常~~

public class Demo15 {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            long startTime = System.currentTimeMillis();
            try {
                Thread.sleep(2000);
                long endTime = System.currentTimeMillis();
                System.out.println("休眠时间:" + (endTime - startTime));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
    }
}

我们可以搞个计时器来记录一下休眠的情况

但是要注意的是,此处结果肯定不一定是2000,因为创建线程,启动main等等之类的行为也是需要时间的,所以我们只是保证一定会 >= 2000就说明确实是有休眠存在的~~

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐