Java_11 多线程与锁
1 多线程
1.1 实现多线程
写法1:继承Thread
类
class Worker extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i ++ ) {
System.out.println("Hello! " + this.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Main {
public static void main(String[] args) {
Worker worker1 = new Worker();
Worker worker2 = new Worker();
worker1.setName("thread-1");
worker2.setName("thread-2");
worker1.start();
worker2.start();
}
}
写法2:实现Runnable
接口
class Worker1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i ++ ) {
System.out.println("Hello! " + "thread-1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
class Worker2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i ++ ) {
System.out.println("Hello! " + "thread-2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Main {
public static void main(String[] args) {
new Thread(new Worker1()).start();
new Thread(new Worker2()).start();
}
}
1.2 常用API
- start():开启一个线程
- Thread.sleep(): 休眠一个线程
- join():等待线程执行结束(才会继续执行主线程等)
- interrupt():从休眠中中断线程
- setDaemon():将线程设置为守护线程。当只剩下守护线程时,程序自动退出;应用:当需要一个线程在其他线程结束之后自动结束,就可以将其设成守护线程
-
interrupt():从休眠中中断线程
-
setDaemon():将线程设置为守护线程
2 锁
- lock:获取锁,如果锁已经被其他线程获取,则阻塞
- unlock:释放锁,并唤醒被该锁阻塞的其他线程
import java.util.concurrent.locks.ReentrantLock;
class Worker extends Thread {
public static int cnt = 0;
//定义一把锁
private static final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
for (int i = 0; i < 100000; i ++ ) {
lock.lock();//执行操作前,先获得锁
try {
cnt ++ ;
} finally {
lock.unlock();//释放锁
}
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Worker worker1 = new Worker();
Worker worker2 = new Worker();
worker1.start();
worker2.start();
worker1.join();
worker2.join();
System.out.println(Worker.cnt);
}
}
3 同步(Synchronized)
- 语法糖,简化加锁写法
写法1:将Synchronized加到代码块上
Synchronized作用在一个对象上,当有很多线程调用时候,只会有一个线程得到这个对象。
class Count {
public int cnt = 0;
}
class Worker extends Thread {
public final Count count;
public Worker(Count count) {
this.count = count;
}
@Override
public void run() {
synchronized (count) {
for (int i = 0; i < 100000; i ++ ) {
count.cnt ++ ;
}
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Count count = new Count();
Worker worker1 = new Worker(count);
Worker worker2 = new Worker(count);
worker1.start();
worker2.start();
worker1.join();
worker2.join();
System.out.println(count.cnt);
}
}
写法2:将Synchronized加到函数上(锁加到了this对象上)
class Worker implements Runnable {
public static int cnt = 0;
private synchronized void work() {
for (int i = 0; i < 100000; i ++ ) {
cnt ++ ;
}
}
@Override
public void run() {
work();
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Worker worker = new Worker();
Thread worker1 = new Thread(worker);
Thread worker2 = new Thread(worker);
worker1.start();
worker2.start();
worker1.join();
worker2.join();
System.out.println(Worker.cnt);
}
}
3.1 wait与notify
- wait(int n) :最多等n毫秒
只能用在Synchronized代码里面
package org.yxc;
class Worker extends Thread {
private final Object object;//方便使用Synchronized
private final boolean needWait;
public Worker(Object object, boolean needWait) {
this.object = object;
this.needWait = needWait;
}
@Override
public void run() {
synchronized (object) {
try {
if (needWait) {//如果某些进程需要等待
object.wait();//当前进程等待,相当于释放锁,别的线程可以访问
System.out.println(this.getName() + ": 被唤醒啦!");
} else {
object.notifyAll();//唤醒全部线程
//object.notify();//随机唤醒一个,写两行就是随机唤醒两个,以此类推
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
for (int i = 0; i < 5; i ++ ) {
Worker worker = new Worker(object, true);
worker.setName("thread-" + i);
worker.start();
}
Worker worker = new Worker(object, false);
worker.setName("thread-5");
Thread.sleep(1000);
worker.start();
}
}