前言:最近在学习java多线程技术,现将学到的知识点汇总,待以后查看。
进程:是拥有资源的最小单位,进程之间彼此相互隔离。
线程:是CPU调度的最小单元,1个或多个线程组成1个进程,进程中的线程彼此共享进程中的资源。
方式一:继承Thread
/**
* create thread
* method1: extends Thread
*
* step1: extends Thread
*/
public class CreateThreadByExtendsThread extends Thread {
/**
* step2: override run method
*/
@Override
public void run(){
System.out.println("I am creating thread by extends Thread");
}
}
调用:
CreateThreadByExtendsThread thread1 = new CreateThreadByExtendsThread();
thread1.start();
方式二:实现Runnable接口
/**
* create thread
* method2: implements Runnable
*
* step1: implements Runnable
*/
public class CreateThreadByImpRunnable implements Runnable {
/**
* step2: override run Method
*/
@Override
public void run() {
System.out.println("I am creating thread by implements Runnable");
}
}
调用:
CreateThreadByImpRunnable runnable = new CreateThreadByImpRunnable();
/**
* step3、as parameter of Thread Constructed function
*/
Thread thread2 = new Thread(runnable);
thread2.start();
方式三:实现Callable接口
/**
* create thread
* method3:impl Callable
*
* step1:implements Callable
* work out:Callable有类型参数泛型,如下面的;该类型泛型确定了call()的返回结果类型。不指定就是Object
*/
public class CreateThreadByImpCallable implements Callable<String>{
private String param;
public CreateThreadByImpCallable(String param){
this.param = param;
}
/**
* step2:implements call method
*/
@Override
public String call() throws Exception {
System.out.println(this.param+"call method operate return");
return this.param+"call method operate return";
}
}
调用:
/**
* 3、check create thread method for implements Callable
*/
CreateThreadByImpCallable createThreadByImpCallable = new CreateThreadByImpCallable("createThread by implements Callable");
/**
* step 3:as parameter of FutureTask Constructed function
* Callable depends FutureTask
*/
FutureTask task = new FutureTask(createThreadByImpCallable);
Thread thread3 = new Thread(task);
thread3.start();
三种方式的比较:
1)、避免JAVA单继承限制
2)、代码可以被多个线程共享
3)、适合多个相同程序代码的线程去处理同一资源的情况
4)、线程池中只能放入实现了Runable或Callable的线程,不能放入继承Thread的线程。
1)、实现Callable的线程可以返回执行结果;而实现Runnable的线程没法返回执行结果。
2)、实现Callable需要实现call()且允许抛出异常;而实现Runnable的线程需要实现run()但不允许抛出异常,只能内部处理。
3)、加入线程池,Runnable使用ExecutorService的execute方法,Callable使用submit方法。
注意:
1)、Callable支持返回执行结果,但是调用的是FutureTask的get方法,同时该方法会阻塞主线程直到获取返回结果,不调用该方法,主线程不会阻塞。
eg:
/**
* 3、check create thread method for implements Callable
*/
long startTime = System.currentTimeMillis();
System.out.println(Thread.currentThread()+",执行起始时间:"+startTime);
CreateThreadByImpCallable createThreadByImpCallable = new CreateThreadByImpCallable("createThread by implements Callable");
/**
* step 3:as parameter of FutureTask Constructed function
* Callable depends FutureTask
*/
FutureTask task = new FutureTask(createThreadByImpCallable);
Thread thread3 = new Thread(task);
thread3.start();
//System.out.println("Class get result:"+task.get());
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread()+",执行结束时间:"+endTime);
System.out.println(Thread.currentThread()+",耗时时间:"+(endTime-startTime));
执行结果:
Thread[main,5,main],执行起始时间:1529406136707
Thread[main,5,main],执行结束时间:1529406136708
Thread[main,5,main],耗时时间:1
call print :createThread by implements Callablecall method operate return
放开注释掉的代码再看一下执行结果:
Thread[main,5,main],执行起始时间:1529406181867
call print :createThread by implements Callablecall method operate return
Class get result:createThread by implements Callablecall method operate return
Thread[main,5,main],执行结束时间:1529406181879
Thread[main,5,main],耗时时间:12
明显较之前耗时长
static方法,获取当前线程,即获取目前正在执行的线程
判断调用该方法的线程是否处于活动状态——线程启动但尚未结束
static方法,让当前线程休眠指定毫秒
获取线程唯一标识
让调用该方法的线程处于中断状态,注意该方法只是给线程标记一个中断状态,但并不会停止线程
static方法,判断当前线程是否处于中断状态,调用该方法后会清除中断状态
public static void testInterrupted(){
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt?"+Thread.interrupted());
Thread thread = new Thread(){
Override
public void run(){
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt ?"+Thread.interrupted());
try {
Thread.sleep(2000);
System.out.println("interrupt");
this.interrupt();
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt ?"+Thread.interrupted());
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt ?"+Thread.interrupted());
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt ?"+this.interrupted());
} catch (InterruptedException e) {
e.printStackTrace();
}
}};
/**
* 验证返回的始终是currentThread的状态
*/
System.out.println("thread not start"+"now is "+Thread.currentThread().getName()+",is interrupt ?"+thread.interrupted());
System.out.println("current thread interrupt");
Thread.currentThread().interrupt();
System.out.println("thread not start"+"now is "+Thread.currentThread().getName()+",is interrupt ?"+thread.interrupted());
System.out.println("thread start...");
thread.start();
}
结果:
now is main,is interrupt ?false
thread not startnow is main,is interrupt ?false
current thread interrupt
thread not startnow is main,is interrupt ?true
thread start...
now is Thread-0,is interrupt ?false
interrupt
now is Thread-0,is interrupt ?true
now is Thread-0,is interrupt ?false
now is Thread-0,is interrupt ?false
判断调用该方法的线程是否处于中断状态,调用该方法后不会清除中断状态
public static void testIsInterrupted(){
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt ?"+Thread.interrupted());
Thread thread = new Thread(){
@Override
public void run(){
System.out.println("now is "+Thread.currentThread().getName()+",is interrupt ?"+Thread.interrupted());
try {
Thread.sleep(2000);
System.out.println("interrupt");
this.interrupt();
System.out.println("方法前:now is "+Thread.currentThread().getName()+",is interrupt ?"+this.isInterrupted());
System.out.println("方法后:now is "+Thread.currentThread().getName()+",is interrupt ?"+this.isInterrupted());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
System.out.println("thread not start"+"now is "+Thread.currentThread().getName()+",is interrupt ?"+thread.isInterrupted());
System.out.println("current thread interrupt");
Thread.currentThread().interrupt();
System.out.println("thread not start"+"now is "+Thread.currentThread().getName()+",is interrupt ?"+thread.isInterrupted());
System.out.println("thread start...");
thread.start();
}
结果:
now is main,is interrupt ?false
thread not startnow is main,is interrupt ?false
current thread interrupt
thread not startnow is main,is interrupt ?false
thread start...
now is Thread-0,is interrupt ?false
interrupt
方法前:now is Thread-0,is interrupt ?true
方法后:now is Thread-0,is interrupt ?true
暂停调用该方法的线程,缺点是会独占锁
恢复调用该方法的线程,缺点是会独占锁
static方法,让当前线程释放CPU资源,然后和其他线程一道再次竞争CPU资源,有可能刚刚放弃,马上又获取CPU资源
下面说提及到的停止方式是可行及推荐方法,至于stop这种不靠谱的停止方法就不再介绍。
方式一:异常跳出
public static void testStopThreadByException(){
Thread thread = new Thread("stopThreadByException"){
@Override
public void run(){
try {
for (int i = 0 ;i < 500 ; i++){
System.out.println(Thread.currentThread().getName()+"输出:i = "+i);
if(i == 200) {
throw new InterruptedException();
}
}
System.out.println(Thread.currentThread().getName() + "输出:如果线程没有结束,我会被输出");
} catch (Exception e){
System.out.println(Thread.currentThread().getName() + "输出:进入异常了,结束!!");
}
}
};
thread.start();
}
结果:
stopThreadByException输出:i = 0
...
stopThreadByException输出:i = 200
stopThreadByException输出:进入异常了,结束!!
方式二:interrupt+return
public static void testStopThreadByInterrutFlagAndReturn(){
Thread thread = new Thread("stopThreadByInterrutFlagAndReturn"){
@Override
public void run() {
for (int i = 0; i < 500; i++) {
if(this.isInterrupted()){
return;
}
System.out.println(Thread.currentThread().getName() + "输出:i = " + i);
if (i == 200) {
this.interrupt();
}
}
System.out.println(Thread.currentThread().getName() + "输出:如果线程没有结束,我会被输出");
}
};
thread.start();
}
结果:
stopThreadByException输出:i = 0
...
stopThreadByException输出:i = 200
线程的优先级分为1~10级,大体上是优先级越高越先执行(优先级相差较大时,确实如此;但是优先级相差较小时,执行顺序未必如此)。
线程的优先级可以通过setPriority()来改变。