Java线程常用的操作方法

来源:互联网 发布:wow 1.12数据库 编辑:程序博客网 时间:2024/05/18 21:43

目标:

 了解设置和取得线程的名称。
了解线程的强制运行。
了解线程的休眠。
了解线程的礼让。
了解线程的中断操作。
具体内容:在多线程中所有的操作方法实际上都是从Thread类开始的。所有的操作都是在Thread类之中的。

线程操作的主要方法

NO方法名称类型描述1public Thread(Runnable   target)构造接收Runnable接口子类对象,实例化Thread对象2public Thread(Runnable target,String  name)构造接收Runnable接口子类对象,实例化Thread对象,并设置线程名称3public Thread(String  name)构造实例化Thread对象,并设置线程名称。4public static Thread currentThread()普通返回目前正在执行的线程。5public final String getName()普通返回线程的名称6public final int getPriority()普通返回线程的优先级7public boolean isInterrupted()普通判断目前线程是否被中断,如果是,返回true,否则返回false8public final boolean isActive()普通判断线程是否在活动,如果是返回true,否则返回false9public final void join() throws InterruptedException普通等待线程死亡10public final synchronized void join(long millis) throws  InterruptedException 普通等待millis毫秒后,线程死亡。11public void run()普通执行线程12public  final  void setName()普通设定线程名称13public final void  setPriority(int newPriority)普通设定线程的优先级14public static void sleep(long millis) throwsInterruptedException普通使目前正在执行的线程休眠millis毫秒15public void start()普通开始执行线程。16public static void yield()普通将目前正在执行的线程暂停一次,允许其他线程执行17public final void setDaemon(boolean on)普通将一个线程设置成后台运行18public final void setPriority(int   newPriority)普通更改线程的优先级

线程名称

 取得和设置线程名称
在Thread类中,可以通过getName()方法取得线程名称,通过setName()方法设置线程的名称。
线程的名称一般在启动线程前设置,但也允许为已经存在的线程设置名称。允许两个Thread对象有相同的名字,但为了清晰,应该尽量避免这种情况的发生。
另外,如果程序并没有为线程指定名称,则系统会自动的为线程分配一个名称。

线程的名称最好在线程启动前设置,避免重名。
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() ;// 系统自动设置线程名称}};


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

取得当前线程

程序可以通过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()方法}};

此时发现,程序中由主方法直接通过线程对象调用里面的run()方法,所以输出的结果中包含了一个“main”,此线程就是“mt.run”, 因为调用此语句是由主方法完成的,也就是说实际上主方法本身也是一个线程——主线程。
  问题:既然主方法都是以线程的形式出现的,那么Java运行时到底启动了多少个线程?
  回答:至少启动了两个。从目前的知识上看,每当Java程序执行的时候,实际上都会启动一个JVM,每一个JVM实际上就是在操作系统中启动了一个进程。Java中本身具备了垃圾收集机制,所以Java运行时至少启动两个线程:主线程、GC。

判断线程是否启动

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()) ; // 判断是否启动}};
      
发现调用start方法之后线程就激活了,如果线程执行任务完毕后就会被关闭。如果没有执行完毕,仍处于激活状态。

线程的强制运行

在线程操作中,可以使用join()方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续运行。
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 ThreadJoinDemo{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) ;}}};

线程的休眠

在程序中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。
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 ThreadSleepDemo{public static void main(String args[]){MyThread mt = new MyThread() ;// 实例化Runnable子类对象Thread t = new Thread(mt,"线程");// 实例化Thread对象t.start() ;// 启动线程}};
会发现每隔500毫秒,执行一次。

线程的中断

 当一个线程运行的时候,另外一个线程可以直接通过interrupt()方法 中断其运行状态。
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 ThreadInterruptDemo{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() ;// 中断线程执行}};


后台进程

在Java中,只要有一个程序没有执行完(一个线程在运行),则整个Java的进程就不会消失,所以此时可以设置一个后台线程,这样即使Java进程结束了,此后台线程依然会继续运行,也就是说不影响进程的结束。要想实现这样的操作,直接使用setDaemon()方法即可。
class MyThread implements Runnable{// 实现Runnable接口public void run(){// 覆写run()方法while(true){System.out.println(Thread.currentThread().getName() + "在运行。") ;}}};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() ;// 启动线程}};
会发现没有打印任何东西,如果设置为false的话则会一直打印,不会结束进程。

线程的优先级

在Java的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时哪个线程的优先级高,哪个线程就有可能被先执行。

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 ThreadPriorityDemo{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() ;// 启动线程}};


主线程的优先级是NORM_PRIORITY 为5 是中等级别。
默认的线程优先级也是NORM_PRIORITY。
程序示例如下:
public class MainPriorityDemo{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) ;}};

线程的礼让

 在线程操作中,也可以使用yield()方法将一个线程的操作暂时让给其他线程执行。
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 ThreadYieldDemo{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() ;}};


总结:

重点是掌握线程的操作方法,对于这些操作方法只需要从Thread类中查找即可。

线程操作范例

实例要求:设计一个线程操作类,要求可以产生三个线程对象,并可以分别设置三个线程的休眠时间,如下所示:
线程A,休眠10秒。
线程B,休眠20秒
线程C,休眠30秒

分析:已知线程的实现有两种方式,一种是继承Thread类,另外一种是实现Runnable接口。而且在类中应该保存线程名称和休眠时间两个属性。

(一)使用Thread类
在Thread类中直接存在了name属性。
class MyThread extends Thread{private int time ;public MyThread(String name,int time){super(name) ;// 设置线程名称this.time = time ;// 设置休眠时间}public void run(){try{Thread.sleep(this.time) ;// 休眠指定的时间}catch(InterruptedException e){e.printStackTrace() ;}System.out.println(Thread.currentThread().getName() + "线程,休眠"+ this.time + "毫秒。") ;}};public class ExecDemo01{public static void main(String args[]){MyThread mt1 = new MyThread("线程A",10000) ;// 定义线程对象,指定休眠时间MyThread mt2 = new MyThread("线程B",20000) ;// 定义线程对象,指定休眠时间MyThread mt3 = new MyThread("线程C",30000) ;// 定义线程对象,指定休眠时间mt1.start() ;// 启动线程mt2.start() ;// 启动线程mt3.start() ;// 启动线程}};

(二)使用Runnable
如果使用Runnable接口,则类中是没有线程名称存在的,所以应该单独建立一个name属性,以保存线程的名称。
class MyThread implements Runnable{private String name ;private int time ;public MyThread(String name,int time){this.name = name ;// 设置线程名称this.time = time ;// 设置休眠时间}public void run(){try{Thread.sleep(this.time) ;// 休眠指定的时间}catch(InterruptedException e){e.printStackTrace() ;}System.out.println(this.name + "线程,休眠"+ this.time + "毫秒。") ;}};public class ExecDemo02{public static void main(String args[]){MyThread mt1 = new MyThread("线程A",10000) ;// 定义线程对象,指定休眠时间MyThread mt2 = new MyThread("线程B",20000) ;// 定义线程对象,指定休眠时间MyThread mt3 = new MyThread("线程C",30000) ;// 定义线程对象,指定休眠时间new Thread(mt1).start() ;// 启动线程new Thread(mt2).start() ;// 启动线程new Thread(mt3).start() ;// 启动线程}};


0 0
原创粉丝点击