Java并发

一、使用线程

//实现Runnable接口
public class MyRunnable implements Runnable { @Override public void run() { // ... } }
public static void main(String[] args) {
    MyRunnable instance = new MyRunnable(); //Runnable实例
    Thread thread = new Thread(instance); //Thread实例
    thread.start(); //使用Thread实例的start()方法来启动线程
}
//实现Callable接口
public class MyCallable implements Callable<Integer> { public Integer call() { return 123; //与Runnable相比,Callable可以有返回值 } } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable mc = new MyCallable(); //Callable实例 FutureTask<Integer> ft = new FutureTask<>(mc); //返回结果用FutureTask封装 Thread thread = new Thread(ft); //Thread实例 thread.start();//使用Thread实例的start()方法来启动线程 System.out.println(ft.get()); //输出返回值 }
//继承Thread类
/*当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,
当一个线程被调度时会执行该线程的 run() 方法。*/ public class MyThread extends Thread { public void run() { // ... } } public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); }

 总之来说实现接口更好,因为:java不支持多重继承,因此继承Thread类之后便无法继承其他的类,但是可以实现多个接口;其次,继承整个Thread类开销过大。

二、基础线程机制

三、中断

四、互斥同步

Java主要提供了两种锁机制来控制多个线程对共享资源的互斥访问。

JVM实现的Synchronized和JDK实现的ReentrantLock

对于Synchronized:

同步一个代码块时:对同一个对象才会同步,如果作用于不同对象上的同步代码块,则不会同步。

同步一个方法时和同步代码块一样,也是作用于同一个对象才会同步

同步一个类时:两个线程调用同一个类的不同对象也会同步。

对于ReentrantLock:

同步从new ReentrantLock()开始,直到lock.unlock()的中间代码部分。

两者比较:

锁的实现

synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的。

性能

新版本 Java 对 synchronized 进行了很多优化,例如自旋锁等,synchronized 与 ReentrantLock 大致相同。

等待可中断

当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。

ReentrantLock 可中断,而 synchronized 不行。

公平锁

公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。

synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非公平的,但是也可以是公平的。

锁绑定多个条件

一个 ReentrantLock 可以同时绑定多个 Condition 对象。

使用选择

除非需要使用 ReentrantLock 的高级功能,否则优先使用 synchronized。这是因为 synchronized 是 JVM 实现的一种锁机制,JVM 原生地支持它,而 ReentrantLock 不是所有的 JDK 版本都支持。并且使用 synchronized 不用担心没有释放锁而导致死锁问题,因为 JVM 会确保锁的释放。

五、线程之间的协作

1.join()

原文地址:https://www.cnblogs.com/lovema1210/p/14526910.html