——- android培训、java培训、期待与您交流! ———-
1 停止线程
原理:让run方法结束。而run方法中通常定义循环结构,所以就是控制住循环结构就可以了。
stop方法已经过时了。
如何控制循环结构??
1 定义结束标记
2 当线程处于了冻结状态,没有执行标记,程序一样无法结束。
这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。
但是会发生InterruptedException异常。
//1 定义结束标记结束线程
class StopThread implements Runnable
{
boolean flag = true;//定义标记控制循环结构
//覆盖run方法
public void run()
{
while(flag)
{
System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
}
}
//改变标记
public void changeFlag()
{
flag = false;
}
}
class StopThreadDemo
{
public static void main(String[] args)
{
StopThread st = new StopThread();//建立实现了Runnable接口的类的对象
Thread t1 = new Thread(st);//建立线程1
Thread t2 = new Thread(st);//建立线程2
t1.start();//启动线程1,调用run方法
t2.start();//启动线程2,调用run方法
//定义一个循环,等线程1和线程2运行一会儿之后,主线程再把标记flag改为false
int num = 0;
while(true)
{
if(num++ == 50)
{
st.changeFlag();//改变run方法中while循环的标记
break;//改变标记后,立刻结束主线程的while循环
}
System.out.println(Thread.currentThread().getName()+"......run"+num);//展示主线程执行的结果
}
System.out.println("over");//表示主线程执行完毕
}
}
部分运行结果:
Thread-0…run
Thread-0…run
Thread-1…run
Thread-0…run
main……run50
Thread-0…run
Thread-1…run
over
从控制台中,可以看到,当主线程运行while循环50次后,
就从while循环中跳出来,并执行结束了。
而且线程1和线程也结束了。
下面看一下当线程处于冻结状态时候如何结束线程
class StopThread implements Runnable
{
boolean flag = true;//定义标记控制循环结构
//覆盖run方法,注意只有在同步中才可以使用wait
public synchronized void run()
{
while(flag)
{
try
{
wait();
}
catch (InterruptedException e)
{
System.out.println(Thread.currentThread().getName()+"...异常");
flag = false;//中断线程的冻结状态后,立即改变标记,结束循环,结束run,结束线程
}
System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
}
}
}
class StopThreadDemo
{
public static void main(String[] args)
{
StopThread st = new StopThread();//建立实现了Runnable接口的类的对象
Thread t1 = new Thread(st);//建立线程1
Thread t2 = new Thread(st);//建立线程2
t1.start();//启动线程1,调用run方法
t2.start();//启动线程2,调用run方法
//定义一个循环,等线程1和线程2运行一会儿之后,主线程再把标记flag改为false
int num = 0;
while(true)
{
if(num++ == 50)
{
t1.interrupt();//强制清楚线程1的冻结状态
t2.interrupt();//强制清楚线程1的冻结状态
break;//改变标记后,立刻结束主线程的while循环
}
System.out.println(Thread.currentThread().getName()+"......run"+num);//展示主线程执行的结果
}
System.out.println("over");//表示主线程执行完毕
}
}
在把run方法改为下面这样的时候
public synchronized void run()
{
while(flag)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
}
System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
}
}
运行结果显示:
线程1和线程2一调用run方法就陷入冻结状态。
而且,直到主线程结束,它们也没有结束。
对此,我们利用interrupt方法来强制中断线程的冻结状态。
总结:
特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();
2 线程中一些常见的方法
2.1 守护线程
setDaemon(boolean)
:将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,
只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
把前面结束线程的例子改动一下。
class StopThread implements Runnable
{
boolean flag = true;//定义标记控制循环结构
//覆盖run方法,
public void run()
{
while(flag)
System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
}
}
class StopThreadDemo
{
public static void main(String[] args)
{
StopThread st = new StopThread();//建立实现了Runnable接口的类的对象
Thread t1 = new Thread(st);//建立线程1
Thread t2 = new Thread(st);//建立线程2
t1.setDaemon(true);//标记线程1为后台线程
t2.setDaemon(true);//标记线程2为后台线程
t1.start();//启动线程1,调用run方法
t2.start();//启动线程2,调用run方法
//定义一个循环,等线程1和线程2运行一会儿之后,主线程再把标记flag改为false
int num = 0;
while(true)
{
if(num++ == 50)
{
break;//改变标记后,立刻结束主线程的while循环
}
System.out.println(Thread.currentThread().getName()+"......run"+num);//展示主线程执行的结果
}
System.out.println("over");//表示主线程执行完毕
}
}
运行结果
Thread-0…run
Thread-1…run
main……run50
Thread-1…run
Thread-0…run
Thread-1…run
over
Thread-1…run
结果显示:当主线程结束之后,线程1和线程2立刻结束了
2.2 join方法
join方法:抢夺CPU执行权,直到该线程执行结束,才放弃CPU执行权。
例如,当主线程碰到t1.join()时,主线程就挂起,让出CPU给线程t1,
当线程t1结束后,主线程才重新启动。
示例如下。
class Join implements Runnable
{
public void run()
{
for(int i =0;i < 50; i++)
{
System.out.println(Thread.currentThread().toString()+"is running..."+i);
Thread.yield();
}
}
}
class JoinDemo
{
public static void main(String[] args)throws InterruptedException
{
Join j =new Join();
Thread t1 = new Thread(j);
Thread t2 = new Thread(j);
//t1.setPriority(Thread.MIN_PRIORITY);
t1.start();
//t1.setPriority(Thread.MAX_PRIORITY);
//t1.join();//线程t1调用Join方法,观察main打印结果
t2.start();
/*
for(int i = 0;i < 60; i++)
System.out.println(Thread.currentThread().getName()+"is running............"+i);*/
System.out.println("over");
}
}
运行结果显示,当线程t1运行完毕之后,才开始执行t2和主线程。
小结:
join():什么意思?等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。
A什么时候运行呢?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。
2.3 yield方法
yield:临时暂停,可以让线程是释放执行权。
在run方法里面添加Thread.yield();
结果为:
Thread[Thread-0,5,main]is running…0
Thread[Thread-1,5,main]is running…1
Thread[Thread-0,5,main]is running…1
Thread[Thread-0,5,main]is running…2
Thread[Thread-0,5,main]is running…3
Thread[Thread-1,5,main]is running…2
Thread[Thread-0,5,main]is running…4
Thread[Thread-1,5,main]is running…3
Thread[Thread-0,5,main]is running…5
Thread[Thread-1,5,main]is running…4
Thread[Thread-0,5,main]is running…6
Thread[Thread-1,5,main]is running…5
两线程在交替执行。
yield()达到了平均分配CPU的效果
3 线程组和优先级
线程组:谁开启就属于谁。样例如下:
Thread[Thread-0,10,main]is running…49
Thread[Thread-1,5,main]is running…49
默认优先级为5,只有1,5,10最明显
public static final int MIN_PRIORITY = 1;
public static final int MAX_PRIORITY = 10;
public static final int NORM_PRIORITY = 1;
4 wait和sleep的区别
wait和sleep的区别:
wait:释放cpu执行权,释放同步中锁。
sleep:释放cpu执行权,不释放同步中锁。