多线程开发之基本线程机制

Thread.yield():

对静态方法 Thread.yield() 的调用声明了当前线程已经完成了生命周期中最重要的部分,可以切换给其它线程来执行。该方法只是对线程调度器的一个建议,而且也只是建议具有相同优先级的其它线程可以运行。

/**
 * Thread.yield()
 * */

public class test1 implements Runnable{
    private int index;
    private int id;
    test1(int index){
        id = index;
    }
    @Override
    public void run() {
        while(true){
            System.out.println("线程"+id+"执行中");
            Thread.yield();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new test1(i)).start();
        }
    }
}

Executor:

CachedThreadPool:为每个任务都创建一个线程
FixedThreadPool:限制线程的数量,每次需要线程的事件处理器,通过直接从线程池中获取线程,使用完将线程放回线程池,多有线程都会一致存于线程池,知道显示的执行shutdown()方法
SingleThreadExecutor:可以将其看成大小为1的FixedThreadPool
CachedThreadPool:
/**
 * Executor
 * CachedThreadPool:为每个任务都创建一个线程
 * */
public class test2 implements Runnable{
    private int id;
    test2(int id){
        this.id = id;
    }
    @Override
    public void run() {
        System.out.println("线程"+id);
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 3; i++) {
            exec.execute(new test2(i));
        }
        exec.shutdown();
    }
}
FixedThreadPool:
/**
 * Executor
 * FixedThreadPool:所有任务只能使用固定大小的线程;
 * */
public class test3 implements Runnable{
    private int id;
    test3(int id){
        this.id = id;
    }
    @Override
    public void run() {
        System.out.println("线程"+id);
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 3; i++) {
            exec.execute(new test3(i));
        }
        exec.shutdown();
    }
}

SingleThreadExecutor:

/**
 * Executor
 * FixedThreadPool:所有任务只能使用固定大小的线程;
 * */

public class test4 implements Runnable{
    @Override
    public void run() {
        System.out.println("线程执行");
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newSingleThreadExecutor();
        exec.execute(new test4());
        exec.shutdown();
    }
}

三种方式的选择

CachedThreadPool在程序执行过程中通常会创建与所需数量相同的线程,然后在它回收旧线程时停止创建新线程,因此它是合理的Executor的首选。只有当这种方式会引发问题时,我们才需要考虑切换到FixedThreadPool。

sleep()

Thread.sleep(millisec) 方法会休眠当前正在执行的线程,millisec 单位为毫秒。

sleep() 可能会抛出 InterruptedException,因为异常不能跨线程传播回 main() 中,因此必须在本地进行处理。线程中抛出的其它异常也同样需要在本地进行处理。

sleep()调用的时候回阻塞当前进程执行其他进程,可用 Interrupted()中断当前进程,进程阻塞的时候不会释放锁。

/**
 * sleep()
 * */

public class SleepTest implements Runnable{
    private int id;
    SleepTest(int id){
        this.id = id;
    }

    @Override
    public void run() {
        System.out.println("线程"+id+"before");
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程"+id+"after");
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 1; i <= 5; i++) {
            exec.execute(new SleepTest(i));
        }
        exec.shutdown();
    }
}

优先级

可以在任意时刻使用setPriority()设置优先级,使用getPriority()读取现用线程的优先级

/**
 * priority
 * */
public class PriorityTest implements Runnable{
    private int priority;
    private int id;
    public PriorityTest(int id,int priority){
        this.priority = priority;
        this.id = id;
    }

    @Override
    public void run() {
        Thread.currentThread().setPriority(priority);
        System.out.println("线程"+id+"running");
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 1; i <= 3; i++) {
            exec.execute(new PriorityTest(i,Thread.MIN_PRIORITY));
        }
        exec.execute(new PriorityTest(4,Thread.MAX_PRIORITY));//我们会发现线程4会比线程123先执行
        exec.shutdown();
    }
}

后台线程 Daemon:

守护线程(后台线程)是程序运行时在后台提供服务的线程,不属于程序中不可或缺的部分。

当所有非守护线程结束时,程序也就终止,同时会杀死所有守护线程。

main() 属于非守护线程。

使用 setDaemon() 方法将一个线程设置为守护线程

/**
 * Daemon
 * */
public class Daemon implements Runnable{
    private int id;
    public Daemon(int id){
        this.id = id;
    }

    @Override
    public void run() {
        System.out.println("线程"+id+"running");
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 20; i++) {
            Thread daemon = new Thread(new Daemon(i));
            daemon.setDaemon(true);
            daemon.start();
        }
        /*20条线程并没有都运行完毕*/
        TimeUnit.MILLISECONDS.sleep(1);//不加这条堵会儿主线程,主线程结束后所有后台线程都被结束,一条后台线程的输出结果都看不到
    }
}

共同学习共同成长,若有错误,欢迎指出

原文地址:https://www.cnblogs.com/czsy/p/10531560.html