1.继承Thread类,重写run()方法
- class MyThread extends Thread{
- @Override
- public void run() {
- System.out.println("hello thread");
- }
- }
- public class Demo1 {
- public static void main(String[] args) {
- MyThread t=new MyThread();//把线程和线程要完成的任务耦合在一起
- t.start();//另外启动新线程,执行run中的逻辑,是一个单独执行流,和现有执行流不相关。并发执行
- System.out.println("hello main");
- }
- }
2.实现Runnable接口,重写run()方法
- class MyRunnable implements Runnable{
- @Override
- public void run() {
- while (true) {
- System.out.println("hello MyRunnable");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
- public class Demo2 {
- public static void main(String[] args) {
- MyRunnable myRunnable=new MyRunnable();
- Thread t=new Thread(myRunnable);//把线程要干的事和线程分开,使用Runnable专门表示线程要完成的工作
- t.start();
- while (true){
- System.out.println("hello main");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
3.继承Thread类,使用匿名内部类
- public class Demo3 {
- /**
- *使用匿名内部类,创建thread子类同时实例化出一个thread对象
- * @param args
- */
- public static void main(String[] args) {
- Thread t=new Thread(){
- @Override
- public void run() {
- while(true){
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- };
- t.start();
- while(true){
- System.out.println("hello main");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
4.实现Runnable接口,使用匿名内部类
- public class Demo4 {
- /**
- * 使用匿名内部类 实现Runnable接口
- * @param args
- */
- public static void main(String[] args) {
- Thread t=new Thread(new Runnable() {
- @Override
- public void run() {
- while(true){
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- });
- t.start();
- while(true){
- System.out.println("hello main");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
5.使用lambda表达式(推荐)
- public class Demo5 {
- /**
- * lambda表达式,推荐写法
- * @param args
- */
- public static void main(String[] args) {
- Thread t=new Thread(()->{
- while (true){
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- });
- t.start();
- while(true){
- System.out.println("hello main");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
- class MyThread extends Thread{
- @Override
- public void run() {
- while(true) {
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
- public class Demo1 {
- public static void main(String[] args) {
- MyThread t=new MyThread();
- //t.run();直接调用run
- t.start();
- while (true){
- System.out.println("hello main");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
第一个截图是调用start,是创建线程,在新线程里面执行代码,和main线程并发执行。
第二个截图是调用run,没有创建线程,而是在原来的main线程执行代码
本质是让run方法快点结束,而不是让run执行一般中止。
方法1:自己定义一个标志位,作为线程是否结束的标志
- public class Demo9 {
- public static boolean isQuit=false;//自定义一个标志
- public static void main(String[] args) {
- Thread t=new Thread(()->{
- while (!isQuit) {
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- });
- t.start();
-
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- isQuit=true;//3秒后线程结束
- }
- }
方法2:使用标准库自带的标记
- public class Demo10 {
- public static void main(String[] args) {
- Thread t = new Thread(() -> {
- while (!Thread.currentThread().isInterrupted()) {
- //currentThread()是一个静态方法,通过它可以获得当前线程对应的Thread对象
- //isInterrupted()用于判定标志位
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- //throw new RuntimeException(e);
-
- //1.立即结束线程
- //break;
-
- //2.不做处理
-
- //3.稍后处理
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ex) {
- throw new RuntimeException(ex);
- }
- break;
- }
- }
- });
- t.start();
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- t.interrupt();//通过他中断线程,设置标志位为true
- /*
- interrupt方法有两种情况
- 1.t线程在运行时,会设置标志位为true
- 2.t线程在阻塞状态(sleep),不会设置标志位,而是触发InterruptedException,这个异常会把sleep提前唤醒.
- 所以处理异常时直接break;
- */
- }
- }
线程之间的调度是不确定的,可以通过join()方法控制线程的结束顺序
- public class Demo11 {
- public static void main(String[] args) {
- Thread t=new Thread(()->{
- for (int i = 0; i < 5; i++) {
- System.out.println("hello thread");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- });
- t.start();
- try {
- t.join();//main线程进入阻塞,t线程继续参与调度
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- System.out.println("hello main");
-
- }
- }
如果调用join方法之前,t线程已经结束,此时join不需要阻塞等待。
操作系统管理线程PCB的时候,是有多了链表的。其中有阻塞队列,就绪队列,调用sleep()时PCB会从 就绪队列移动 到 阻塞队列。只有就绪队列才会参与cpu调度,当sleep时间到了就会从新回到就绪队列(不代表立即在cpu上执行)