线程操作API
1.currentThread
2.getId() 、getName()、getPriority()、getStart、isAlive()、isDaemon()、isInterrupted()
3.setPriority()、
4.setDaemon()、
5、sleep()、
6、yield()、
7、join()、
8、interrupt()
---------------------------------------------------------------------
1. Thread.currentThread方法
Thread的静态方法currentThread方法可以用于获取运行当前代码片段的线程。
Thread current = Thread.currentThread();
1 /** 2 * 获取当前代码块的线程 3 * @author Administrator 4 * 5 */ 6 7 class TestThreadDemo4{ 8 public static void main(String[] args) { 9 /* 10 * 当程序运行起来时 Os 会启动一个进程来运行 11 * JVM ,而进程启动后会创建一个线程,用这个线程来运行Main方法 12 */ 13 //这里获取的是运行main方法的线程 14 Thread t =Thread.currentThread(); 15 System.out.println("运行main方法的线程是:"+t); 16 17 //main 方法中调用 18 testCurrent(); 19 //创建线程 20 Thread t1 =new Thread(){ 21 @Override 22 public void run() { 23 super.run(); 24 System.out.println("运行T1线程是:"+Thread.currentThread()); 25 testCurrent(); 26 } 27 }; 28 t1.start(); 29 30 31 } 32 /** 33 * 输出调用当前方法的线程 34 */ 35 public static void testCurrent(){ 36 System.out.println("运行testCurrendt方法的线程是:"+Thread.currentThread()); 37 } 38 }
运行main方法的线程是:Thread[main,5,main]
运行testCurrendt方法的线程是:Thread[main,5,main]
运行T1线程是:Thread[Thread-0,5,main]
运行testCurrendt方法的线程是:Thread[Thread-0,5,main]
2. 获取线程信息
Thread提供了 获取线程信息的相关方法:
long getId():返回该线程的标识符 全局唯一的 不能重复
String getName():返回该线程的名称
int getPriority():返回线程的优先级
Thread.state getState():获取线程的状态
boolean isAlive():测试线程是否处于活动状态
boolean isDaemon():测试线程是否为守护线程
boolean isInterrupted():测试线程是否已经中断
1 /** 2 * 获取线程信息的相关方法 3 * @author Administrator 4 * 5 */ 6 class TeatThreadDemo{ 7 public static void main(String[] args) { 8 //获取调用main方法的线程 9 Thread main =Thread.currentThread(); 10 System.out.println("ID:"+main.getId()); 11 System.out.println("name:"+main.getName()); 12 System.out.println("优先级:"+main.getPriority()); 13 System.out.println("状态:"+ main.getState()); 14 System.out.println("是否活动:"+ main.isAlive()); 15 System.out.println("是否为守护进程"+ main.isDaemon()); 16 System.out.println("是否被中断:"+main.isInterrupted()); 17 } 18 }
3. 线程优先级
线程的切换是由线程调度控制的,我们无法通过代码来干涉,但是我们可以通过提高线程的优先级来最大程度的改善线程获取时间片的几率。
线程的优先级被划分为10级,值分别为1-10,其中1最低,10最高。线程提供了3个常量来表示最低,最高,以及默认优先级:
Thread.MIN_PRIORITY,
Thread.MAX_PRIORITY,
Thread.NORM_PRIORITY
设置优先级的方法为:
void setPriority(int priority)
1 /** 2 * 线程优先级 3 * 线程优先级有10个级别 1-10 4 * 1最小,有常量对应 MIN_PRIORITY 5 * 10最大 有常量对应 MAX_PRIORITY 6 * 5为默认优先级 也有常量对应 NORM_PRIORITY 7 * 理论上优先级越高的线程获取时间片的册数越多 8 * @author Administrator 9 * 10 */ 11 public class TestThreadDemo6 { 12 public static void main(String[] args) { 13 Thread min =new Thread(){ 14 @Override 15 public void run() { 16 17 super.run(); 18 for(int i=0;i<100;i++){ 19 System.out.println("min"); 20 } 21 } 22 }; 23 Thread max =new Thread(){ 24 @Override 25 public void run() { 26 27 super.run(); 28 for(int i=0;i<100;i++){ 29 System.out.println("max"); 30 } 31 } 32 }; 33 Thread norm =new Thread(){ 34 @Override 35 public void run() { 36 37 super.run(); 38 for(int i=0;i<100;i++){ 39 System.out.println("norm"); 40 } 41 } 42 }; 43 min.setPriority(Thread.MIN_PRIORITY); 44 max.setPriority(Thread.MAX_PRIORITY); 45 min.start(); 46 max.start(); 47 norm.start(); 48 } 49 }
4. 守护线程
守护线程与普通线程在表现上没有什么区别,我们只需要通过Thread提供的方法来设定即可:
void setDaemon(boolean )
当参数为true时该线程为守护线程。
守护线程的特点是,当进程中只剩下守护线程时,所有守护线程强制终止。
GC就是运行在一个守护线程上的。
需要注意的是,设置线程为后台线程要在该线程启动前设置。
GC就是运行在一个守护线程上的。
需要注意的是,设置线程为后台线程要在该线程启动前设置。
Thread daemonThread = new Thread();
daemonThread.setDaemon(true);
daemonThread.start();
/** * 测试守护线程:前台线程和后台线程 * @author Administrator * */ class TestDemo1{ public static void main(String[] args) { /* * rose 扮演者:前台线程 * */ Thread rose =new Thread(){ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=0;i<10;i++){ System.out.println("rose:let me go"); } System.out.println("rose:aaaaaaa"); System.out.println("音效:普通"); } }; /* * jack 是后台线程 * */ Thread jack =new Thread(){ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=0;i<10;i++){ System.out.println("jack:you jump i jump!"); } System.out.println("jack:a弄弄哦aaaaaa"); System.out.println("音效:扑通!"); } }; //将jack设置为后台线程 jack.setDaemon(true); rose.start(); jack.start(); //加上这句话的效果 while(true); } }
5. sleep方法
Thread的静态方法sleep用于使当前线程进入阻塞状态:
static void sleep(long ms)
该方法会使当前线程进入阻塞状态指定毫秒,当指定毫秒阻塞后,当前线程会重新进入Runnable状态,等待分配时间片。
该方法声明抛出一个InterruptException。所以在使用该方法时需要捕获这个异常。
/** * Sleep 阻塞 * */ class TestThreadDemo8{ public static void main(String[] args) { //实现一个电子表功能 /* * 每秒输出一下当前系统时间--> 11:12:55 * 1.创建SimpleDateFormate 指定时间格式 * 2.创建当前系统时间所对应Date对象 * 3.通过SimpleDateFormate的format方法将date转换为字符串 * 4.想实现电子表功能 就循环每隔1秒执行一次2,3步骤 */ SimpleDateFormat sdf =new SimpleDateFormat("HH:mm:ss"); while(true){ Date now =new Date(); System.out.println(sdf.format(now)); try { Thread.sleep(1000); //每输出一次时间后阻塞1秒钟 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
注:该程序可能会出现"跳秒"现象,因为阻塞一秒后线程并非是立刻回到running状态,而是出于runnable状态,等待获取时间片。那么这段等待时间就是"误差"。所以以上程序并非严格意义上的每隔一秒钟执行一次输出。
6. yield方法
Thread的静态方法yield:
static void yield()
该方法用于使当前线程主动让出当次CPU时间片回到Runnable状态,等待分配时间片。
7. join方法
Thread的方法join:
void join()
该方法用于等待当前线程结束。此方法是一个阻塞方法。
该方法声明抛出InterruptException。
1 /** 2 * join 3 * @author Administrator 4 *本身并发的线程是没有先后顺序的 5 */ 6 7 class TestThreadDemo23{ 8 /* 9 * 图片是否下载完毕 这个写在main函数以外的原因 是因为 10 * run 局部函数调用 局部变量 需要final修饰 如果这样就没法修改 11 */ 12 private static boolean isfinish =false; 13 public static void main(String[] args) { 14 final Thread download =new Thread(){ 15 @Override 16 public void run() { 17 super.run(); 18 System.out.println("download: 开始下载图片"); 19 for(int i=0;i<100;i++){ 20 System.out.println("download:已经下载了%"+i); 21 try { 22 Thread.sleep(100); 23 } catch (InterruptedException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } 27 } 28 isfinish =true; 29 System.out.println("下载完毕"); 30 } 31 }; 32 33 Thread show =new Thread(){ 34 public void run() { 35 System.out.println("show:显示其他信息"); 36 System.out.println("show:显示图片。。"); 37 //这里应当等待download线程工作完毕 38 try{ 39 download.join(); 40 }catch(InterruptedException e){ 41 e.printStackTrace(); 42 } 43 if (!isfinish){ 44 System.out.println("show: 显示图片失败"); 45 }else{ 46 System.out.println("show:图片显示完毕"); 47 } 48 } 49 50 }; 51 download.start(); 52 show.start(); 53 } 54 }
8.interrupt()
进程中断异常
interrupt方法好多初学者会感到困惑,发现一些情况下并不能终止线程。在java API中有对此详细的说明:
如果线程在调用 Object
类的 wait()
、wait(long)
或 wait(long, int)
方法,或者该类的join()
、join(long)
、join(long, int)
、sleep(long)
或 sleep(long, int)
方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException
。
如果该线程在可中断的通道
上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个
ClosedByInterruptException
。
因此,可以看出,interrupt之后作用到 wait() join() 已经sleep()上
/** * 进程中断异常 * @author Administrator * */ class TestThreadDemo10{ public static void main(String[] args) { /* * 林永健 处于睡眠阻塞的线程 */ final Thread lin =new Thread(){ @Override public void run() { super.run(); System.out.println("林:刚美完容,睡觉吧"); try { Thread.sleep(1000000); } catch (InterruptedException e) { // TODO Auto-generated catch block System.out.println("林:干嘛呢!干嘛呢"); } } }; /* * 黄宏 用于中断程序的线程 */ Thread huang =new Thread(){ @Override public void run() { System.out.println("黄:开始砸墙"); for(int i=0;i<10;i++){ System.out.println("黄:80"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("黄:搞定"); lin.interrupt(); //中断lin这个线程 } }; lin.start(); huang.start(); } }