【Java多线程系列二】Thread类的方法

Thread实现Runnable接口并实现了大量实用的方法。

/*
 * 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机会,它自己也有可能再次得到执行机会
 */
public static native void yield();

/*
 * 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将得到执行机会,在休眠时间结束后,当前线程继续执行
 */
public static native void sleep(long millis) throws InterruptedException;

/*
 * 一旦调用后宿主线程将阻塞,待当前线程结束后继续
 */
public final void join() throws InterruptedException;

/*
 * 一旦调用后宿主线程将阻塞,待当前线程结束后继续
 */
public final synchronized void join(long millis)throws InterruptedException;

/*
 * 中断线程
 */
public void interrupt();

/*
 * on=true表示线程标记为守护线程(例如GC线程),若正在运行的所有线程都是守护线程,JVM将退出
 */
public final void setDaemon(boolean on);

 Java代码:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.Test;

/**
 * @Description: 测试Thread的方法
 */
public class ThreadMethodsTest {

    static String SLEEP = "sleep";
    static String YIELD = "yield";
    static String JOIN = "join";
    
    private Map<String, ThreadMethodEnum> map = new ConcurrentHashMap<>();

    class ThreadSleep implements Runnable {
        private int millis;
        
        public ThreadSleep(int millis) {
            this.millis = millis;
        }
        
        @Override
        public void run() {
            System.out.println("Thread sleep run()...");
            long threadId = Thread.currentThread().getId();
            
            ThreadMethodEnum sleep = ThreadMethodEnum.SLEEP;
            sleep.init(threadId);
            
            try {
                Thread.sleep(millis);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sleep.stop();
            map.put(sleep.getMethod(), sleep);
        }
    }
    
    class ThreadYield implements Runnable {
        @Override
        public void run() {
            long threadId = Thread.currentThread().getId();
            ThreadMethodEnum yield = ThreadMethodEnum.YIELD;
            yield.init(threadId);
            Thread.yield();
            yield.stop();
            map.put(yield.getMethod(), yield);
        }
    }
    
    class ThreadJoin implements Runnable {
        private Thread thread;
        private int millis = 0;
        
        public ThreadJoin(Thread thread) {
            this.thread = thread;
        }
        
        public ThreadJoin(Thread thread, int millis) {
            this.thread = thread;
            this.millis = millis;
        }
        
        @Override
        public void run() {
            try {
                System.out.println("Thread join run()...");
                long threadId = Thread.currentThread().getId();
                ThreadMethodEnum join = ThreadMethodEnum.JOIN;
                join.init(threadId);
                if (millis > 0) {
                    this.thread.join(millis);
                } else {
                    this.thread.join();
                }
                join.stop();
                map.put(join.getMethod(), join);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    final AtomicInteger interruptCount = new AtomicInteger(0);
    final int interruptIndex = 100;
    
    class ThreadInterrupt extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
                interruptCount.incrementAndGet();
                if (interruptCount.intValue() == interruptIndex) {
                    interrupt();
                }
            }
        }
    }
    
    
    @Test
    public void testSleep() throws InterruptedException {
        int millis = 1000;
        Thread sleep = new Thread(new ThreadSleep(millis));
        sleep.start();
        sleep.join();
        ThreadMethodEnum tme = map.get(SLEEP);
        // 预期sleep时间与millis相近
        Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) * 1.0 / millis));
    }
    
    @Test
    public void testYield() throws InterruptedException {
        Thread yield = new Thread(new ThreadYield());
        yield.start();
        yield.join();
        ThreadMethodEnum tme = map.get(YIELD);
        // 预期yield消耗时间几乎为0
        Assert.assertEquals(1, Math.round(tme.getStartTimeMillis() * 1.0 / tme.getStopTimeMillis()));
    }
    
    @Test
    public void testJoin() throws InterruptedException {
        System.out.println("testJoin() ----  start----");
        int millis = 1000;
        Thread sleep = new Thread(new ThreadSleep(millis));
        sleep.setName("Sleep Thread");
        sleep.start();
        Thread join = new Thread(new ThreadJoin(sleep));
        join.setName("Join Thread");
        join.start();
        join.join();
        ThreadMethodEnum tme = map.get(SLEEP);
        // 预期sleep时间与millis相近
        Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) * 1.0 / millis));
        tme = map.get(JOIN);
        // 预期join阻塞时间与millis相近
        Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) * 1.0 / millis));
        System.out.println("testJoin() ----  end----");
    }
    
    @Test
    public void testJoinMillis() throws InterruptedException {
        System.out.println("testJoinMillis() ----  start----");
        int millis = 500;
        Thread sleep = new Thread(new ThreadSleep(millis * 2));
        sleep.setName("Sleep Thread");
        sleep.start();
        Thread join = new Thread(new ThreadJoin(sleep, millis));
        join.setName("Join Thread");
        join.start();
        join.join();
        
        ThreadMethodEnum tme = map.get(SLEEP);
        //预期sleep 不能在join阻塞结束前设置,固为null
        Assert.assertTrue(tme == null);
        
        tme = map.get(JOIN);
        //预期join阻塞时间与millis相近
        Assert.assertEquals(1, Math.round((tme.getStopTimeMillis() - tme.getStartTimeMillis()) / millis));
        System.out.println("testJoinMillis() ----  end----");
    }
    
    @Test
    public void testInterrupt() throws InterruptedException {
        ThreadInterrupt interrupt = new ThreadInterrupt();
        interrupt.start();
        interrupt.join();
        Assert.assertEquals(interruptIndex, interruptCount.intValue());
    }
    
}

enum ThreadMethodEnum {
    SLEEP(ThreadMethodsTest.SLEEP) {
        @Override
        public void init(long threadId) {
            super.start(threadId);
        }
    },
    YIELD(ThreadMethodsTest.YIELD) {
        @Override
        public void init(long threadId) {
            super.start(threadId);
        }
    },
    JOIN(ThreadMethodsTest.JOIN) {
        @Override
        public void init(long threadId) {
            super.start(threadId);
        }
    };
    
    private String method;
    private long threadId;
    private long startTimeMillis;
    private long stopTimeMillis = 0;
    
    private ThreadMethodEnum(String method) {
        this.method = method;
    }
    
    public void stop() {
        this.stopTimeMillis = System.currentTimeMillis();
    }
    
    public String getMethod() {
        return method;
    }
    
    public long getThreadId() {
        return threadId;
    }
    
    public long getStartTimeMillis() {
        return startTimeMillis;
    }
    
    public long getStopTimeMillis() {
        return stopTimeMillis;
    }

    private void start(long threadId) {
        this.threadId = threadId;
        this.startTimeMillis = System.currentTimeMillis();
    }
    
    public abstract void init(long threadId);
}

猜你喜欢

转载自www.cnblogs.com/zhaoyibing/p/9569655.html