Java多线程核心技术学习之线程的创建、停止、优先级

前言:最近在学习java多线程技术,现将学到的知识点汇总,待以后查看。

1、线程和进程的区别

进程:是拥有资源的最小单位,进程之间彼此相互隔离。
线程:是CPU调度的最小单元,1个或多个线程组成1个进程,进程中的线程彼此共享进程中的资源。

2、线程的创建

方式一:继承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、实现Runnable、Callable接口较继承Thread的优点

1)、避免JAVA单继承限制
2)、代码可以被多个线程共享
3)、适合多个相同程序代码的线程去处理同一资源的情况
4)、线程池中只能放入实现了Runable或Callable的线程,不能放入继承Thread的线程。

2、实现Runnable和实现Callable的区别

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
明显较之前耗时长

3、方法介绍

3.1、currentThread

static方法,获取当前线程,即获取目前正在执行的线程

3.2、isAlive

判断调用该方法的线程是否处于活动状态——线程启动但尚未结束

3.3、sleep

static方法,让当前线程休眠指定毫秒

3.4、getId

获取线程唯一标识

3.5、interrupt

让调用该方法的线程处于中断状态,注意该方法只是给线程标记一个中断状态,但并不会停止线程

3.6、interrupted

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

3.7、isInterrupted

判断调用该方法的线程是否处于中断状态,调用该方法后不会清除中断状态

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

3.8、suspend

暂停调用该方法的线程,缺点是会独占锁

3.9、resume

恢复调用该方法的线程,缺点是会独占锁

3.10、yield

static方法,让当前线程释放CPU资源,然后和其他线程一道再次竞争CPU资源,有可能刚刚放弃,马上又获取CPU资源

4、线程的停止

下面说提及到的停止方式是可行及推荐方法,至于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

5、线程优先级

线程的优先级分为1~10级,大体上是优先级越高越先执行(优先级相差较大时,确实如此;但是优先级相差较小时,执行顺序未必如此)。
线程的优先级可以通过setPriority()来改变。

你可能感兴趣的:(多线程)