一、取得和设置线程的名称
1.取得线程名称
package 多线程基础;
public class GetNameThread extends Thread
{
public void run()
{
for(int i=0;i<3;i++)
{
printMsg(); //当前的其他线程调用printMsg()方法
try {
Thread.sleep(1000); //睡眠1s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void printMsg()
{
Thread t=Thread.currentThread(); //获得当前线程的名字
String name=t.getName();
System.out.println("name = "+name);
}
public static void main(String [] args)
{
GetNameThread t1=new GetNameThread();GetNameThread t2=new GetNameThread();
t1.start();
for(int i=0;i<5;i++)
{
t1.printMsg(); //主线程调用printMsg()方法
try {
Thread.sleep(1000); //主线程睡眠1s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
name = main
name = Thread-0
name = main
name = Thread-0
name = Thread-0
name = main
name = main
name = main
run( )方法只是类的一个普通方法而已,如果直接调用run( )方法,程序中依然只有主线程这一个线程,其程序执行路径依然只有一条,也就是说一旦run( )方法被调用,程序还要顺序执行,只有run( )方法具体执行完毕后,才可执行其后的代码,这样并没有达到多线程并发执行的目的。就如下面的代码,把t1.start();注释掉发现输出,只有main线程。
package 多线程基础;
public class GetNameThread extends Thread
{
public void run()
{
for(int i=0;i<3;i++)
{
printMsg(); //当前的其他线程调用printMsg()方法
try {
Thread.sleep(1000); //睡眠1s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void printMsg()
{
Thread t=Thread.currentThread(); //获得当前线程的名字
String name=t.getName();
System.out.println("name = "+name);
}
public static void main(String [] args)
{
GetNameThread t1=new GetNameThread();GetNameThread t2=new GetNameThread();
//t1.start();
for(int i=0;i<5;i++)
{
t1.printMsg(); //主线程调用printMsg()方法
try {
Thread.sleep(1000); //主线程睡眠1s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
name = main
name = main
name = main
name = main
name = main
2.设置线程的名称
package 多线程基础;
public class GetSetName implements Runnable
{
public void run ()
{
Thread temp=Thread.currentThread();
System.out.println("当前线程的名称:"+temp.getName()); //取得当前线程的名字
}
public static void main(String[] args) {
System.out.println("NI好!");
Thread t=new Thread(new GetSetName());
t.setName("我叫张昊雨!"); //设置线程的名字
t.start();
}
}
输出:
NI好!
当前线程的名称:我叫张昊雨!
二、判断线程是否启动
用到isAlive( ) 方法
package 多线程基础;
public class StartThread extends Thread
{
public void run()
{
for(int i=0;i<5;i++)
{
printMsg();
}
}
public void printMsg()
{
//获取当前线程的引用
Thread t=Thread.currentThread();
String name =t.getName();
System.out.println("name = "+name);
}
public static void main(String[] args)
{
StartThread t=new StartThread();
//设置线程名字
t.setName("张昊雨");
System.out.println("调用start()之前,t.isalive()="+t.isAlive());
t.start();
System.out.println("调用start()之后,t.isalive()="+t.isAlive());
for(int i=0;i<5;i++)
{
t.printMsg();
}
//下面语句输出的结果是不固定的,有时输出false,有时输出true
System.out.println("Main方法结束时,t.isalive="+t.isAlive());
}
}
输出:
调用start()之前,t.isalive()=false
调用start()之后,t.isalive()=true
name = main
name = main
name = main
name = 张昊雨
name = 张昊雨
name = 张昊雨
name = 张昊雨
name = 张昊雨
name = main
name = main
Main方法结束时,t.isalive=false
三、守护线程与setDaemon方法
守护线程也叫后台线程,它是指用户程序在运行时后台提供的一种通用服务的线程。
例如垃圾回收的线程就属于守护线程
当线程中只剩下守护线程时JVM就会退出,如果还有其他的用户线程在,JVM就不会退出
查看Thread源码可知:
private boolean daemon = false;
意味着默认创建的线程都属于偶同的用户线程。只有调用setDaemon(true)之后,才能转为守护线程。
package 多线程基础;
public class ThreadDaemon
{
public static void main(String [] args)
{
Thread t=new Thread(new Threadtest());
t.setDaemon(true); //设置为守护线程,一定要在start()之前
t.start();
try { //睡眠1毫秒,避免可能出现的没有输出的现象
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Threadtest implements Runnable
{
public void run()
{
for(int i=0;true;i++) {
System.out.println(i+" "+Thread.currentThread().getName()+"is running");
}
}
}
输出:
0 Thread-0is running
1 Thread-0is running
2 Thread-0is running
3 Thread-0is running
4 Thread-0is running
5 Thread-0is running
6 Thread-0is running
7 Thread-0is running
8 Thread-0is running
9 Thread-0is running
10 Thread-0is running
11 Thread-0is running
12 Thread-0is running
13 Thread-0is running
14 Thread-0is running
15 Thread-0is running
16 Thread-0is running
17 Thread-0is running
18 Thread-0is running
19 Thread-0is running
20 Thread-0is running
21 Thread-0is running
22 Thread-0is running
23 Thread-0is running
24 Thread-0is running
25 Thread-0is running
26 Thread-0is running
27 Thread-0is running
28 Thread-0is running
29 Thread-0is running
在这1毫秒之内输出了这些。虽然说run( ) 方法里的for循环是死循环,但因为该线程被设置成为守护线程,因此整个进程在主线程main结束后就随之停止了。可以想象,若果将t.setDaemon(true);注释掉,就会无限输出了。哈哈哈
四、线程的联合
用到join( ) 方法
package 多线程基础;
public class ThreadJoin {
public static void main(String[] args)
{
Thread ppThread=new Thread(new ttttt());
ppThread.start();
int i=0;
for(int x=0;x<5;x++)
{
if(i==3)
{
try {
ppThread.join(); //强制执行完ppThread线程后,再运行后面的程序,此时相当于main线程挂起了.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main Thread"+i);
i++;
}
}
}
class ttttt implements Runnable
{
public void run()
{
int i=0;
for(int x=0;x<5;x++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---->"+i);
i++;
}
}
}
输出:
main Thread0
main Thread1
main Thread2
Thread-0---->0
Thread-0---->1
Thread-0---->2
Thread-0---->3
Thread-0---->4
main Thread3
main Thread4
在i=3时
主线程会阻塞,直到ppThread线程执行完main线程才会继续执行
五、线程的中断
范例1
package 多线程基础;
public class SleepInterrupt implements Runnable{
public void run() {
try{
System.out.println( "在run()方法中 - 这个线程休眠10秒" );
Thread.sleep( 10000 );
System.out.println( "在run()方法中 - 继续运行" );
}
catch( InterruptedException x ){
System.out.println( "在run()方法中 - 中断线程" );
//return;
}
System.out.println( "在run()方法中 - 休眠之后继续完成" );
System.out.println( "在run()方法中 - 正常退出" );
}
public static void main( String[] args ){
SleepInterrupt si = new SleepInterrupt();
Thread t = new Thread( si );
t.start();
// 在此休眠是为确保线程能运行一会
try{
Thread.sleep( 2000 );
}
catch( InterruptedException e ){
e.printStackTrace();
}
System.out.println( "在main()方法中 - 中断其它线程" );
t.interrupt(); //在main线程中断 t 线程
System.out.println( "在main()方法中 - 退出" );
}
}
输出;
在run()方法中 - 这个线程休眠10秒
在main()方法中 - 中断其它线程
在main()方法中 - 退出
在run()方法中 - 中断线程
在run()方法中 - 休眠之后继续完成
在run()方法中 - 正常退出
t 线程并没有休眠10s,而是休眠2s后背主线程中断了,它会抛出异常被catch抓到,所以会输出 在run()方法中 - 中断线程 这句话
范例2
package 多线程基础;
public class InteruptCheck
{
public static void main( String[] args )
{
Thread t = Thread.currentThread();
System.out.println( "A:t.isInterrupted() = " + t.isInterrupted() );
//中断的是main线程
t.interrupt();
System.out.println( "B:t.isInterrupted() = " + t.isInterrupted() );
System.out.println( "C:t.isInterrupted() = " + t.isInterrupted() );
try
{
Thread.sleep( 2000 );
System.out.println( "线程没有被中断" );
}
catch( InterruptedException x )
{
System.out.println( "线程被中断" );
}
//因为sleep抛出了异常,所以它清除了中断标志
System.out.println( "D:t.isInterrupted() = " + t.isInterrupted() );
}
}
输出:
A:t.isInterrupted() = false
B:t.isInterrupted() = true
C:t.isInterrupted() = true
线程被中断
D:t.isInterrupted() = false