多线程(2)

首先回顾一下创建线程的几种写法:

1.直接通过继承Thread来实现多线程.

 class MyThread extends Thread{
        public void run(){
            while(true){
                System.out.println("hello,Thread");
                try {
                    Thread.sleep(1000);//就是让线程主动进入"阻塞状态",主动放弃去CPU上执行.时间到了
                    //之后,线程才会解除阻塞状态,重新被调度到CPU上执行.
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    public class Demo1{
        public static void main(String[] args){
            Thread t=new MyThread();
            t.start();
            while(true){
                System.out.println("hello,main");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

2.通过实现Runnable接口,重写run,把Runnable实例传入到Thread中.

class MyRunnable implements Runnable{
    public void run(){
        while(true){
            System.out.println("hello,Thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
           }
        }
    }
}
public class Demo2 {
    public static void main(String[] args){
        Thread T=new Thread(new MyRunnable());
        T.start();
        while(true){
            System.out.println("hello,main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

3.针对1进行变形,使用匿名内部类继承Thread并重写run方法. 

public class Demo3 {
    public static void main(String[] args){
        Thread t=new Thread(){
            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 {
    public static void main(String[] args){
        Thread T=new Thread(new Runnable(){
            public void run(){
                while(true){
                    System.out.println("hello,Thread");
                    try {
                        Thread.sleep(1000);//休眠,就是让线程主动进入"阻塞状态",主动放弃进入CPU上去执行.
                        //时间到了之后,线程才会解除阻塞状态,重新被调度到CPU上去执行.
                    } 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表达式,lambda本质上就是针对匿名内部类的平替. 

public class Demo5{
    public static void main(String[] args){
        Thread t=new Thread(()->{
           //lambda相当于平替了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);
            }
        }
    }
}

上述这五种写法本质上都是,1.要把线程执行的任务内容列出来 2.通过Thread的start来创建/启动系统中的线程.Thread对象和操作系统内核中的线程是一一对应的.

接下来介绍Thread这个类的一些方法和属性.

1.Thread()   说明:创建线程对象.      2.Thread(Runnable xxx)  说明:使用Runnable对象创建线程对象

3.Thread(String name)  说明: 创建线程对象,并给线程对象命名.

4.Thread(Runnable xxx,String name)  说明:使用Runnable对象创建线程,并对线程进行命名.

1,2已经介绍过了,这里介绍一下3.4 代码如下:

public class Demo6 {
    public static void main(String[] args){
        Thread t=new Thread("自定义线程"){
          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);
            }
        }
    }
}
public class Demo7 {
    public static void main(String[] args){
        Thread t=new Thread(new Runnable(){
            public void run(){
                while(true){
                    System.out.println("hello,Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        },"自定义线程");
        t.start();
    }
}

 

通过下面可以看到成功给创建的进程命名了

 

第二个代码并没有看到main线程,原因是main线程执行的太快了,已经执行完毕.main线程执行完毕之后就会销毁.

Thread类的属性

ID :注意这里的ID是和PCB上的ID不同,是JVM自己的.获取方法是 getId()

public class Demo8 {
    public static void main(String[] args){
        Thread t=new Thread(()->{
           while(true){
               System.out.println("一个线程");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        t.start();
        System.out.println(t.getId());

    }
}

可以看到这个线程的ID是24.

名称:获取方法是 getName()

public class Demo8 {
    public static void main(String[] args){
        Thread t=new Thread(()->{
           while(true){
               System.out.println("一个线程");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        t.start();
        System.out.println(t.getId());
        System.out.println(t.getName());
    }
}

 

状态:获取方法 getState()

public class Demo8 {
    public static void main(String[] args){
        Thread t=new Thread(()->{
           while(true){
               System.out.println("一个线程");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        System.out.println(t.getId());
        System.out.println(t.getName());
        System.out.println(t.getState());
    }
}

可以看到上述代码的状态是NEW

优先级:获取方法 getPriority() 

public class Demo8 {
    public static void main(String[] args){
        Thread t=new Thread(()->{
           while(true){
               System.out.println("一个线程");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        System.out.println(t.getId());
        System.out.println(t.getName());
        System.out.println(t.getState());
        System.out.println(t.getPriority());
    }
}

 是否后台线程:获取方法 isDaemon()   还是刚才的代码,执行这个获取方法 isDaemin()得到的结果如下:

 表示创建的这个线程不是后台线程,这里介绍一下这个名词.

后台线程:这样的线程即使还在继续执行,也不能阻止java进程结束.

前台线程:这样的线程如果还没有执行完的话,此时java进程是一定不会结束的.

在java代码中,main线程就是前台线程.另外程序员创造出来的线程,默认情况下都是前台线程.可以通过setDaemon()的方法把线程设置为后台线程.

如下,t默认是前台线程,当main线程执行完后,进程不会结束,t线程还在执行会继续打印.但是当把t线程设置为后台线程的时候,当main线程执行完后,进程会立即结束,停止打印.

public class Demo8 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true) {
                System.out.println("一个线程");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }
}

可以看到由于main线程执行完之后,进程就结束了,此时t线程还没有打印.这里要注意的是t.setDaemon()一定要在t.start()的前面. 但也有打印一次的情况.如下:

出现的原因主要是,线程之间是抢占式执行的,调度顺序不确定.

是否存活:指的是系统中的线程(PCB)是否存在. Thread对象的生命周期和PCB的生命周期是不一样的.比如:

public class Demo9 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{

        });
        //这里已经创建了Thread的实例,Thread对象已经诞生了.但是内核中的PCB还内有诞生.
        t.start();
        //通过t.start()才创建出线程.(PCB才真正创建出来并被加入到链表中.)
        Thread.sleep(100000);
        //由于t线程中的啥都没写,t线程的执行瞬间结束,内核中的线程和PCB被销毁.
        //但是在sleep结束之前,t指向的Thread对象还是存在的.此时,就看到,系统中的线程先结束了,但是t仍然存在.
        System.out.println(t.isAlive());
    }
}

中断一个线程:

1.纯自己来实现,控制线程结束

public class Demo10 {
    public static boolean isRunning=true;
    public static void main(String[] args){
        Thread t=new Thread(()->{
           while(isRunning){
               System.out.println("hello,Thread");
           }
            System.out.println("该线程结束执行");
        });
        t.start();
        
        System.out.println("结束执行创建的线程");
        isRunning=false;
    }
}

2.使用Thread提供的interrupt方法和isInterruptted方法,来实现上述的效果. 

public class Demo11 {
    public static void main(String[] args){
        Thread t=new Thread(()->{
           while(!Thread.currentThread().isInterrupted()){
               System.out.println("hello,Thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   break;
               }
           }
            //Thread.currentThread是个静态方法,能够获取到当前线程即t引用.
            //isInterrupted 线程内置的标志位 boolean变量. true表示线程要终止了,false表示线程要继续执行.
        });

        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        t.interrupt();
    }
}

 

 

 

 

 

 

 

 

 

 

  • 43
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值