java多线程 Posted on 2021-06-07 00:00:00 2021-06-07 00:00:00 by Author 摘要 这篇文章是Java多线程的知识,可以帮助自己了解与熟悉多线程的一些知识 ## 一.使用线程 有三种使用线程的方法: - 实现 Runnable 接口; - 实现 Callable 接口; - 继承 Thread 类。 实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以理解为任务是通过线程驱动从而执行的。 **实现Runnable接口** 需要实现接口中的run()方法 ```java public class MyRunnable implements Runnable { @Override public void run() { // ... } } ``` 使用 Runnable 实例再创建一个 Thread 实例,然后调用 Thread 实例的 start() 方法来启动线程。 ```java public static void main(String[] args) { MyRunnable instance = new MyRunnable(); Thread thread = new Thread(instance); thread.start(); } ``` **实现Callable接口** ```java public class MyCallable implements Callable<Integer> { public Integer call() { return 123; } } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable mc = new MyCallable(); FutureTask<Integer> ft = new FutureTask<>(mc); Thread thread = new Thread(ft); thread.start(); System.out.println(ft.get()); } ``` **集成Thread类** 同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。 当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。 ```java public class MyThread extends Thread { public void run() { // ... } } ``` ```java public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); } ``` #### Synchronized 1. 同步代码块:它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进行同步。对于以下代码,使用 ExecutorService 执行了两个线程,由于调用的是同一个对象的同步代码块,因此这两个线程会进行同步,当一个线程进入同步语句块时,另一个线程就必须等待。 ```java public void fun(){ synchronized(this){ //.............. } } ``` #### ReentrantLock ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁。 ```java public class LockExample{ private Lock lock=new ReentrantLock(); public void fun(){ lock.lock(); try{ for(inti =0;i<10;i++){ System.out.println(i+" "); } }finally{ lock.unlock(); } } } ``` ```java public static void main(String[] args) { LockExample lockExample = new LockExample(); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(() -> lockExample.func()); executorService.execute(() -> lockExample.func()); } ``` synchronized是JVM实现的,而ReentrantLock是JDK实现的。ReentrantLock 可中断,而 synchronized 不行。 #### 线程之间的协作 1. join():在线程中调用另一个线程的 join() 方法,会将当前线程挂起,而不是忙等待,直到目标线程结束。对于以下代码,虽然 b 线程先启动,但是因为在 b 线程中调用了 a 线程的 join() 方法,b 线程会等待 a 线程结束才继续执行,因此最后能够保证 a 线程的输出先于 b 线程的输出。 ```java public class JoinExample { private class A extends Thread { @Override public void run() { System.out.println("A"); } } private class B extends Thread { private A a; B(A a) { this.a = a; } @Override public void run() { try { a.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("B"); } } public void test() { A a = new A(); B b = new B(a); b.start(); a.start(); } } ``` ```java public static void main(String[] args) { JoinExample example = new JoinExample(); example.test(); } ``` 2. wait() notify() notifyAll():调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。它们都属于 Object 的一部分,而不属于 Thread。wait()挂起期间会释放锁,因为如果没有释放锁,那么其他线程就无法唤醒或者无法执行notify()或者notifyall(),会造成死锁。 2. wait()和sleep()的区别:wait() 是 Object 的方法,而 sleep() 是 Thread 的静态方法;wait() 会释放锁,sleep() 不会。
{{ item.content }}
{{ child.content }}