线程常用操作方法

来源:互联网 发布:js聚合物水泥防水浆料 编辑:程序博客网 时间:2024/06/09 21:32

在多线程中所有的操作方法都是从Thread类开始的,所有的操作基本上都在Thread类中。

 

1,线程名称

  1,在Thread类中可以通过getName()方法取得线程名称,通过setName()设置线程名称。

  2,线程的名称一般在启动线程前设置,但也允许为运行的线程设置名称,允许两个Thread对象有相同名称,但是应该避免。

  3,如果程序没有为线程指定名称,系统会自动为线程设置名称。

复制代码
class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<3;i++){            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字        }    }};public class ThreadNameDemo{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        new Thread(mt).start() ;        // 系统自动设置线程名称        new Thread(mt,"线程-A").start() ;        // 手工设置线程名称        new Thread(mt,"线程-B").start() ;        // 手工设置线程名称        new Thread(mt).start() ;        // 系统自动设置线程名称        new Thread(mt).start() ;        // 系统自动设置线程名称    }};
复制代码

 

currentThread(),获取当前线程。

 运行结果:

复制代码
线程-A运行,i = 0线程-B运行,i = 0Thread-1运行,i = 0Thread-0运行,i = 0Thread-0运行,i = 1Thread-0运行,i = 2Thread-1运行,i = 1线程-B运行,i = 1Thread-2运行,i = 0线程-A运行,i = 1Thread-2运行,i = 1线程-B运行,i = 2Thread-1运行,i = 2Thread-2运行,i = 2线程-A运行,i = 2
复制代码

  从效果看,指定的名称会自动出现,如果没有指定会发现线程使用自动编号完成,按照Thread-0,Thread-1.依次编号,实际上,肯定在类中存在static属性,用于记录编号

2,当前线程:CurrentThread()

  程序可以通过currentThread()方法取得当前正在运行的线程对象,

复制代码
class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<3;i++){            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字        }    }};public class CurrentThreadDemo{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        new Thread(mt,"线程").start() ;        // 启动线程        mt.run() ;    // 直接调用run()方法    }};
复制代码

  运行结果:

main运行,i = 0线程运行,i = 0main运行,i = 1线程运行,i = 1main运行,i = 2线程运行,i = 2

  此时发现,程序中由主方法直接通过线程对象调用里面的run()方法,所有此时的结果包含一个"main",此线程就是由“mt.run()”产生的,因为调用此语句是由主方法完成的。

也就是说,主方法本身也是一个线程---主线程

  问题:既然主方法都是以线程的形式出现,那么JAVA启动时候运行了多少线程?

  回答:至少启动了两个。

    从之前学习的情况来看,每当JAVA执行,都会启动一个JVM,每一个JVM都是在操作系统中启动一个线程。

    JAVA本身有垃圾回收机制,所以至少启动了两个线程:主线程,GC。

3,判断线程是否在执行:isAlive

  

复制代码
class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<3;i++){            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字        }    }};public class ThreadAliveDemo{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        Thread t = new Thread(mt,"线程");        // 实例化Thread对象        System.out.println("线程开始执行之前 --> " + t.isAlive()) ;     // 判断是否启动        t.start() ;    // 启动线程        System.out.println("线程开始执行之后 --> " + t.isAlive()) ;     // 判断是否启动        for(int i=0;i<3;i++){            System.out.println(" main运行 --> " + i) ;        }        // 以下的输出结果不确定        System.out.println("代码执行之后 --> " + t.isAlive()) ;     // 判断是否启动            }};
复制代码

  运行结果:

复制代码
线程开始执行之前 --> false线程开始执行之后 --> true main运行 --> 0 main运行 --> 1 main运行 --> 2线程运行,i = 0代码执行之后 --> true线程运行,i = 1线程运行,i = 2
复制代码

4,线程强制运行:join()

  可以通过join()方法使得一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后,才可以继续运行

复制代码
package Thread1;class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<50;i++){            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字        }    }};public class demo1{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        Thread t = new Thread(mt,"线程");        // 实例化Thread对象        t.start() ;    // 启动线程        for(int i=0;i<50;i++){            if(i>10){                try{                    t.join() ;    // 线程强制运行                }catch(InterruptedException e){}            }            System.out.println("Main线程运行 --> " + i) ;        }    }};
复制代码

运行结果:

复制代码
线程运行,i = 0Main线程运行 --> 0线程运行,i = 1Main线程运行 --> 1线程运行,i = 2Main线程运行 --> 2线程运行,i = 3线程运行,i = 4线程运行,i = 5线程运行,i = 6线程运行,i = 7线程运行,i = 8线程运行,i = 9Main线程运行 --> 3线程运行,i = 10Main线程运行 --> 4线程运行,i = 11线程运行,i = 12线程运行,i = 13Main线程运行 --> 5线程运行,i = 14Main线程运行 --> 6线程运行,i = 15线程运行,i = 16线程运行,i = 17线程运行,i = 18线程运行,i = 19Main线程运行 --> 7线程运行,i = 20Main线程运行 --> 8线程运行,i = 21Main线程运行 --> 9线程运行,i = 22Main线程运行 --> 10线程运行,i = 23线程运行,i = 24线程运行,i = 25线程运行,i = 26线程运行,i = 27线程运行,i = 28线程运行,i = 29线程运行,i = 30线程运行,i = 31线程运行,i = 32线程运行,i = 33线程运行,i = 34线程运行,i = 35线程运行,i = 36线程运行,i = 37线程运行,i = 38线程运行,i = 39线程运行,i = 40线程运行,i = 41线程运行,i = 42线程运行,i = 43线程运行,i = 44线程运行,i = 45线程运行,i = 46线程运行,i = 47线程运行,i = 48线程运行,i = 49Main线程运行 --> 11Main线程运行 --> 12Main线程运行 --> 13Main线程运行 --> 14Main线程运行 --> 15Main线程运行 --> 16Main线程运行 --> 17Main线程运行 --> 18Main线程运行 --> 19Main线程运行 --> 20Main线程运行 --> 21Main线程运行 --> 22Main线程运行 --> 23Main线程运行 --> 24Main线程运行 --> 25Main线程运行 --> 26Main线程运行 --> 27Main线程运行 --> 28Main线程运行 --> 29Main线程运行 --> 30Main线程运行 --> 31Main线程运行 --> 32Main线程运行 --> 33Main线程运行 --> 34Main线程运行 --> 35Main线程运行 --> 36Main线程运行 --> 37Main线程运行 --> 38Main线程运行 --> 39Main线程运行 --> 40Main线程运行 --> 41Main线程运行 --> 42Main线程运行 --> 43Main线程运行 --> 44Main线程运行 --> 45Main线程运行 --> 46Main线程运行 --> 47Main线程运行 --> 48Main线程运行 --> 49
复制代码

3.5  线程的休眠

   在线程中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。

  sleep定义格式:

public static void sleep(long milis,int nanos)       throws InterruptedException

  首先,static,说明可以由Thread类名称调用,其次throws表示如果有异常要在调用此方法处处理异常

所以sleep()方法要有InterruptedException 异常处理,而且sleep()调用方法通常为Thread.sleep(500) ;形式

  例子:

复制代码
package Thread1;class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<50;i++){            try{                    Thread.sleep(500) ;    // 线程休眠            }catch(InterruptedException e){}            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字        }    }};public class demo1{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        Thread t = new Thread(mt,"线程");        // 实例化Thread对象        t.start() ;    // 启动线程    }};
复制代码

会发现运行过程中,线程名是一个个间隔一定时间出来的,这里达到了休眠效果。

复制代码
线程运行,i = 0线程运行,i = 1线程运行,i = 2线程运行,i = 3线程运行,i = 4线程运行,i = 5线程运行,i = 6线程运行,i = 7线程运行,i = 8线程运行,i = 9线程运行,i = 10线程运行,i = 11线程运行,i = 12线程运行,i = 13线程运行,i = 14线程运行,i = 15线程运行,i = 16线程运行,i = 17线程运行,i = 18线程运行,i = 19线程运行,i = 20线程运行,i = 21线程运行,i = 22线程运行,i = 23线程运行,i = 24线程运行,i = 25线程运行,i = 26线程运行,i = 27线程运行,i = 28线程运行,i = 29线程运行,i = 30线程运行,i = 31线程运行,i = 32线程运行,i = 33线程运行,i = 34线程运行,i = 35线程运行,i = 36线程运行,i = 37线程运行,i = 38线程运行,i = 39线程运行,i = 40线程运行,i = 41线程运行,i = 42线程运行,i = 43线程运行,i = 44线程运行,i = 45线程运行,i = 46线程运行,i = 47线程运行,i = 48线程运行,i = 49
复制代码

3.6 线程的中断

  一个线程可以被另一个线程中断其操作的状态,使用 interrupt()方法完成。

复制代码
package Thread1;class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        System.out.println("1、进入run()方法") ;        try{                Thread.sleep(10000) ;    // 线程休眠10秒                System.out.println("2、已经完成了休眠") ;        }catch(InterruptedException e){            System.out.println("3、休眠被终止") ;        }        System.out.println("4、run()方法正常结束") ;    }};public class demo1{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        Thread t = new Thread(mt,"线程");        // 实例化Thread对象        t.start() ;    // 启动线程        try{                Thread.sleep(2000) ;    // 线程休眠2秒        }catch(InterruptedException e){            System.out.println("3、休眠被终止") ;        }        t.interrupt() ;    // 中断线程执行    }};
复制代码

运行结果:

1、进入run()方法3、休眠被终止4、run()方法正常结束

  会看到,在1到3的时候会因为线程休眠2秒而卡顿了一下。

  但是,既然线程中断了,那么4,这句话不应该打出来的,因此要在3,线程被终止处添加一句话rutrun,表示返回调用处

复制代码
package Thread1;class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        System.out.println("1、进入run()方法") ;        try{                Thread.sleep(10000) ;    // 线程休眠10秒                System.out.println("2、已经完成了休眠") ;        }catch(InterruptedException e){            System.out.println("3、休眠被终止") ;            return ; // 返回调用处        }        System.out.println("4、run()方法正常结束") ;    }};public class demo1{    public static void main(String args[]){        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象        Thread t = new Thread(mt,"线程");        // 实例化Thread对象        t.start() ;    // 启动线程        try{                Thread.sleep(2000) ;    // 线程休眠2秒        }catch(InterruptedException e){            System.out.println("3、休眠被终止") ;        }        t.interrupt() ;    // 中断线程执行    }};
复制代码

运行结果:

1、进入run()方法3、休眠被终止

3.7 后台线程

  在Java中,只要一个线程没有执行完(一个线程在运行),则整个Java的进程不会消失,所以此时可以设置一个后台线程,这样即使java线程结束了,则后台线程

依旧会继续执行。要想实现这个操作,要使用setDaemon()方法完成。

   t.setDaemon(true) ; 

复制代码
class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法
     int i=0; while(true){    //设置死循环,这样来实现线程不断运行,设置后台运行。 System.out.println(Thread.currentThread().getName() + "在运行。"+i) ; } }};public class ThreadDaemonDemo{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 实例化Runnable子类对象 Thread t = new Thread(mt,"线程"); // 实例化Thread对象 t.setDaemon(true) ; // 此线程在后台运行 t.start() ; // 启动线程 }};
复制代码

3.8线程的优先级

  获取优先级的方法:getPriority();

  优先级分为最低,最高,普通三个(Thread.MIN_PRIORITY,Thread.MAX_PRIORITY,Thread.NORM_PRIORITY),

设置优先级:

MyThread  t1=new MyThread();Thread t3 = new Thread(t1,"线程C") ;//实例化线程对象t3.setPriority(Thread.MIN_PRIORITY) ;//设置优先级为最低

例子:

复制代码
package Thread1;class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<5;i++){            try{                    Thread.sleep(500) ;    // 线程休眠            }catch(InterruptedException e){}            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字        }    }};public class demo1{    public static void main(String args[]){        Thread t1 = new Thread(new MyThread(),"线程A") ;    // 实例化线程对象        Thread t2 = new Thread(new MyThread(),"线程B") ;    // 实例化线程对象        Thread t3 = new Thread(new MyThread(),"线程C") ;    // 实例化线程对象        t1.setPriority(Thread.MIN_PRIORITY) ;    // 优先级最低        t2.setPriority(Thread.MAX_PRIORITY) ;    // 优先级最低        t3.setPriority(Thread.NORM_PRIORITY) ;    // 优先级最低        t1.start() ;    // 启动线程        t2.start() ;    // 启动线程        t3.start() ;    // 启动线程    }}; 
复制代码

运行结果:

复制代码
线程B运行,i = 0线程C运行,i = 0线程A运行,i = 0线程B运行,i = 1线程C运行,i = 1线程A运行,i = 1线程B运行,i = 2线程A运行,i = 2线程C运行,i = 2线程B运行,i = 3线程C运行,i = 3线程A运行,i = 3线程B运行,i = 4线程C运行,i = 4线程A运行,i = 4
复制代码

主方法的优先级

  主方法的优先级是NORM_PRIORITY.

复制代码
package Thread1;public class demo1{    public static void main(String args[]){        System.out.println("主方法的优先级:" +             Thread.currentThread().getPriority()) ;    // 取得主方法的优先级        System.out.println("MAX_PRIORITY = " + Thread.MAX_PRIORITY) ;        System.out.println("NORM_PRIORITY = " + Thread.NORM_PRIORITY) ;        System.out.println("MIN_PRIORITY = " + Thread.MIN_PRIORITY) ;    }};
复制代码

运行结果:

主方法的优先级:5MAX_PRIORITY = 10NORM_PRIORITY = 5MIN_PRIORITY = 1

  由此可知,主方法优先级是5,也就是普通优先级,而且主方法是一个线程对象。

3.9 线程的礼让

  yield()方法实现线程的礼让。

复制代码
package Thread1;class MyThread implements Runnable{    // 实现Runnable接口    public void run(){    // 覆写run()方法        for(int i=0;i<5;i++){            try{                Thread.sleep(500) ;  //休眠一下            }catch(Exception e){}            System.out.println(Thread.currentThread().getName()                    + "运行,i = " + i) ;    // 取得当前线程的名字            if(i==2){                System.out.print("线程礼让:") ;                Thread.currentThread().yield() ;    // 首先获取当前线程,然后线程礼让            }        }    }};public class demo1{    public static void main(String args[]){        MyThread my = new MyThread() ;    // 实例化MyThread对象        Thread t1 = new Thread(my,"线程A") ;        Thread t2 = new Thread(my,"线程B") ;        t1.start() ;        t2.start() ;    }};
复制代码

运行结果:

复制代码
线程A运行,i = 0线程B运行,i = 0线程B运行,i = 1线程A运行,i = 1线程A运行,i = 2线程礼让:线程B运行,i = 2线程礼让:线程A运行,i = 3线程B运行,i = 3线程A运行,i = 4线程B运行,i = 4
复制代码
原创粉丝点击