一、 多线程与多进程的区别:
最本质的区别是每个进程拥有自己的一整套变量,而线程则共享数据。 共享变量使得线程之间的通信比进程之
间的通信更有效、更容易。同时,与进程相比,线程更加“轻量级”,创建、撤销一个线程比启动新继承的开销要
小得多。
二、Thread提供的主要方法
- Thread(Runnable r);
- void start();
- void run();
- Thread currentThread();
- static boolean interrupted();
- boolean isInterrupted();
- sleep(long s);
- void interrupt();
- void join();
- void join(long s);
- Thread.State getState();
三、 调用时机与主要区别
①创建线程主要有两种方式,一种是继承Thread,重写run方法,另一种是实现Runnanble接口,并作为Thread的一个参数。代码示例如下:
//继承Thread
class MyThread extends Thread{
@Override
public void run(){
System.out.println("hello my thread");
}
}
Thread thread = new Thread(new MyThread());
//实现Runnable接口
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("hello my runnable");
}
}
Thread thread = new Thread(new MyRunnable());
//也是实现Runnable接口,通常为了方便会使用这种方式
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(2000);
t1.interrupt();
}catch (InterruptedException e){
e.getMessage();
}
}
});
②启动线程
thread.start();
注意:直接调用run方法只是在原来的线程执行run方法与普通的方法并没有区别,而调用是start方法则会新创建一个线程,并在该新线程中执行run方法。
③线程的中断
虽然有强制中断线程的stop方法,但是已经被弃用。现在一般是通过设置中断标志位的方式来实现线程中断。即在线程中执行重复操作时,将线程的中断标志位作为执行循环的条件之一。
a. 通过Thread.currentThread()获取当前线程。
b. 通过thread.isInterrupted()来判断thread这个线程是否被中断置位,true代表被请求中断。
c. 通过Thread.interrupted()来判断执行这条语句的线程是否被中断置位,同时会清除该线程的中断状态。
d. 通过Thread.sleep(s)来使得当前线程进入休眠状态s毫秒(虽然中断和休眠好像没有什么联系,后面会讲)
先来个需求:如果我们有两个线程t1和t2,在t1中循环执行某些操作,同时t2要能决定t1什么时候结束。代码实现:
Thread t1 = new Thread(new Runnable(){
@Override
public void run(){
while(Thread.currentThread.isInterrupted() == false && more work to do){
//more work to do
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run(){
try{
t1.interrupt();
}catch(Exception e){
e.getMessage();
}
}
});
t1.start();
t2.start();
第一个挺简单的,没有什么陷阱,那再来一个,如果这个时候我们要求t1没处理完一次操作要休眠一段时间呢。
看起来好像很简单,之前也被坑过,难道不是直接在t1的循环体内添加Thread.sleep()并捕捉中断异常吗。正常逻辑是如此,可是sleep方法很奇特,如果中断标识被置位时执行sleep方法,sleep不但不休眠而且会清除中断标识的状态,也就是中断标识位和sleep同时“失效”,也就是不按照我们所想的方式执行。那么正确的做法应该是怎样呢。代码如下:
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try{
while(true){
System.out.println(""+x++);
Thread.sleep(1000);//sleep和中断标志位的正确组合用法
}
}catch (InterruptedException e){
e.getMessage();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(2000);
t1.interrupt();
}catch (InterruptedException e){
e.getMessage();
}
}
});
t1.start();
t2.start();
四、小结
①Thread.currentThread().isinterrupted() 与 Thread.interrupted()的主要区别在于前者只做判断,而后者除了做判断外还会清除线程的中断状态。
②Thread.sleep()也会清除线程的中断状态,并且会抛出InterruptedException的异常,从而使得中断状态取消并且不会进入休眠状态。