【Java并发编程四】线程的基本使用二

线程的join(等待线程结束)和yield(谦让线程)

 Thread的join()方法,会阻塞占用Thread线程的其他线程,直到Thread执行完毕,才会释放相应对象。

public class myTest implements Runnable {
    public static int i;
    public static void main(String[] args) throws InterruptedException {
        myTest test = new myTest();
        Thread thread = new Thread(test);
        thread.start();

        /**
         * 不执行,打印的是0。执行,打印的是10000。
         * 参数100,表示线程执行完毕后,会阻塞100ms。
         */
        thread.join(100);
        thread.yield();
        System.out.println("i="+i);
    }
    @Override
    public void run() {
        for(i=0; i<10000; i++) {
        }
    }
}

 join方法:

    public final synchronized void join(final long millis)
    throws InterruptedException {
        if (millis > 0) {
            if (isAlive()) {
                final long startTime = System.nanoTime();
                long delay = millis;
                do {
                    wait(delay);
                } while (isAlive() && (delay = millis -
                        TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0);
            }
        } else if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            throw new IllegalArgumentException("timeout value is negative");
        }
    }

 while循环会判断线程是否存活,若不为存活,则直接跳出循环并使用wait(delay)方法,再去调用notifyAll()方法,唤醒被阻塞的线程。
 线程谦让表示该线程愿意让出CPU资源,给其他线程去调用,可以理解为该线程愿意让出这个资源,大家再度公平竞争。一个例子为有一个线程调用了大量的cpu资源去给线程a运算一个一亿的for循环语句,和一个一百的for循环语句,这样相比cpu会给极大的资源给线程a运算第一个for,但当其运算完成后,第二个for想必不用调用这么多cpu资源去运算,那么便可以使用线程谦让,使得它们再次平衡下来。

线程的wait(等待)和notify(通知)

 wait方法的使用是被锁包围的,首先wait在执行之前会被锁给锁住,不让其它线程获取本线程(线程a)的对象资源,而使用了wait后,他会自动且暂时的释放当前的锁,然后阻塞该线程,等待需要访问该对象的线程b获得对象锁,再使用notify方法后,执行完成线程b的synchronize代码块后,再唤醒线程a,继续执行线程a。

public class myTest {
    final static Object o = new Object();

    public static class test1 implements Runnable {
        @Override
        public void run() {
            synchronized (o) {
                System.out.println("test1");
                try {
                    System.out.println("test1 wait");
                    // 被notify告知了,才会继续执行下去
                    o.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("test1 end");
            }
        }
    }

    public static class test2 implements Runnable {
        @Override
        public void run() {
            synchronized (o) {
                System.out.println("test2");
                System.out.println("test2 wait");
                o.notify();
                System.out.println("test2 end");
            }
        }
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new test1());
        Thread t2 = new Thread(new test2());
        t1.start();
        t2.start();
    }
}

线程的stop(终止)和interrupted(中断)

 stop()方法会破坏对象原子性,因此已被弃用。即使在被synchronize包围时,stop方法也会先去释放锁,再去停止整个线程的,这样在释放锁的过程中,可能会出现一释放锁,该锁立马被别的线程锁获取,并发生了修改对象操作后,便停止了线程,这种数据错误不容易在众多代码出找出来。
 interrupt()方法,线程中断,不会破坏对象的原子性。中断时机,由编写者确定。

package myTest;

public class myTest implements Runnable {
    public static void main(String[] args) {
        Thread t = new Thread(new myTest());
        t.start();
        t.interrupt();
    }
    @Override
    public void run() {
        while(true) {
            if(Thread.currentThread().isInterrupted()) {
                break;
            }
        }
    }
}
    public void interrupt() {
        if (this != Thread.currentThread()) {
            checkAccess();

            // thread may be blocked in an I/O operation
            synchronized (blockerLock) {
                Interruptible b = blocker;
                if (b != null) {
                    interrupted = true;
                    interrupt0();  // inform VM of interrupt
                    b.interrupt(this);
                    return;
                }
            }
        }
        interrupted = true;
        // inform VM of interrupt
        interrupt0();
    }

你可能感兴趣的:(java,开发语言,jvm)