java并发-线程

Posted China2K

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java并发-线程相关的知识,希望对你有一定的参考价值。

前言

近来时间比较充裕,正好又看了一遍《实战java高并发程序设计》,故而对java并发一些知识进行下总结,算是温故而知新吧。

 一,线程基础

1,新建线程

一般有两种实现方式实现Runnable接口或继承Thread类(Thread类本身也是实现Runnable接口)

public class Test {
    public static void main(String[] args) throws Exception {
        Thread t1=new TestThread();
        Thread t2=new TestThread();
        Thread t3=new Thread(new TestThreadImpl());
        Thread t4=new Thread(new TestThreadImpl());
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        }
}
class TestThread extends Thread{
    @Override
    public void run() {
        System.out.println("hello word");
    }
}
class TestThreadImpl implements Runnable{
    @Override
    public void run() {
        System.out.println("hello word 2");
    }
}

 

2,线程的终止

一般来说线程在执行完毕后就会结束无须手动关闭,但凡是总有例外一下服务端的后台线程可能会常驻系统,比如它们本身就是一个无限循环,用于提供默写服务。

Thread 提供了一个被标注为废弃的方法stop();因为stop()方法过于暴力,强行把执行一般的线程终止,这样可能会引起一些数据不一致的问题。《实战java高并发程序设计》中给出了一个的解决方案,用一个一个自定义的stop并且需要自行决定何时退出

class ChangeObjectThread extends Thread{
    volatile boolean stopme=false;
    public void stopMe(){
        stopme=true;
    }
    @Override
    public void run() {
        while(true){
            if(stopme){
                break;
            }
            //synchromized handle data

        }
    }
}

3,线程中断interrupt

严格来讲,线程中断并不会让线程立即退出,而是给线程发送一个通知,告知目标线程 ,有人希望你退出了。至于目标线程街道通知后如何处理,则完全有线程自行决定,如果无条件退出那么又遇到和stop()相同的问题了。

 

public void interrupt() //中断线程
public boolean isInterrupted()//判断是否被中断
public static boolean interrupted()//判断是否被中断,并清除当前中断状态
public class Test {
    public static Object o = new Object();

    public static void main(String[] args) throws Exception {
        Thread t1 = new TestThread();
        t1.start();
        Thread.sleep(1000);
        t1.interrupt();
    }
}

class TestThread extends Thread {
    @Override
    public void run() {
        int i=0;
        while (!isInterrupted()) {
            i++;
            System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  
        }
    }
}

另:当线程由于被调用了sleep(), wait(), join()等方法而进入阻塞状态;若此时调用线程的interrupt()将线程的中断标记设为true。由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常,这时就要用合适的方式处理InterruptedException了

4,Object 等待(wait)和通知(notify)

  这两个方法是由Object类提供的,并不是在Thread中的。当一个对象实例调用了wait()方法后,当前线程就会在这个对象上等待。如:线程A中调用了obj.wait()方法,那么线程A就会停止继续执行,而转为等待状态,直到调用了obj.notify()方法为止。

wait(),notify()方法的调用鼻血包含在对应的synchronized语句中,也就是要先获得目标对象锁资源。调用了wait后,会释放锁资源。

public class Test {
    public static Object o = new Object();

    public static void main(String[] args) throws Exception {
        Thread t1 = new TestThread();
        Thread t2 = new TestThread();
        Thread t3 = new TestThread();
        Thread t4 = new TestThreadNotify();
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }

}

class TestThread extends Thread {
    @Override
    public void run() {
        synchronized (Test.o) {
            try {
                System.out.println(Thread.currentThread().getName()+"waiting....");
                Test.o.wait();
                System.out.println(Thread.currentThread().getName()+"start....");
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"stop....");
        }
    }
}

class TestThreadNotify extends Thread {
    @Override
    public void run() {
        synchronized (Test.o) {
            System.out.println("TestThreadNotify start....");
            try {
                Test.o.notifyAll();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("TestThreadNotify stop....");
        }
    }
}
}
Thread-0waiting....
TestThreadNotify start....
TestThreadNotify stop....
Thread-2waiting....
Thread-1waiting....
Thread-0start....
Thread-0stop....

 

 

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


很多时候,一个线程的输入可能非常依赖于另外一个或者多个线程的输出,此时,这个线程就需要等待依赖线程执行完毕,才能继续执行。JDK 提供了join()操作来实现这个功能,如下所示,显示了2个join()方法:

public final void join() throws InterruptedException

public final synchronized void join(long millis) throws InterruptedException

第一个join()方法表示无限等待,它会一直阻塞当前线程,直到目标线程执行完毕。

第二个方法给出了一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程也会因为“等不及了”,而继续往下执行。

join()的本质是让调用线程wait()在当前线程对象实例上;

public class Test {
    public volatile static int i = 0;
    public static class AddThread extends Thread {
        @Override
        public void run() {
            for (i = 0; i < 10000000; i++);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        AddThread at = new AddThread();
        at.start();
        at.join();
        System.out.println(i);

    }

}

主函数中,如果不使用join()等待AddThread ,那么得到的i 很可能是0或者一个非常小的数字。因为AddThread 还没开始执行,i 的值就已经被输出了。但在使用join()方法后,表示主线程愿意等待AddThread 执行完毕,跟着AddThread 一起往前走,故在join()返回时,AddThread 已经执行完成,故i 总是10000000

yiead()

这是一个静态方法,一旦执行,它会使当前线程让出CPU 。但要注意,让出CPU 并不表示当前线程不执行了。当前线程在让出CPU 后,还会进行CPU 资源的争夺,但是是否能够再次被分配到,就不一定了

 

待续


以上是关于java并发-线程的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程与并发库高级应用-工具类介绍

多个用户访问同一段代码

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段

java开发的项目案例,大厂内部资料

Java进阶之光!2021必看-Java高级面试题总结

Java编程思想-并发