多线程编程
多线程编程模板
多线程编程的通用公式:
- 线程操作资源类
- 高内聚,低耦合
实现步骤:
1、创建资源类
2、资源类中创建同步方法,同步代码块
例如:SaleTicket.java
class Ticket{
private int number=30;
private Lock lock=new ReentrantLock();
public void saleTicket(){
lock.lock();
try
{
if (number>0){
System.out.println(Thread.currentThread().getName()+
"\t卖出第:"+(number--)+"\t还剩下:"+number);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public class SaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(()->{for (int i = 1; i <=40 ; i++) { ticket.saleTicket();}},"A").start();
new Thread(()->{for (int i = 1; i <=40 ; i++) { ticket.saleTicket();}},"B").start();
new Thread(()->{for (int i = 1; i <=40 ; i++) { ticket.saleTicket();}},"C").start();
}
}
Lock
定义:
锁实现提供了比使用同步方法和语句可以获得的更广泛的锁操作。它们允许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对象。
Lock有实现:ReentrantLock可重入锁
使用方式:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
synchronized与Lock的区别:
- synchronized是java内置关键字,在jvm层面。Lock是java类
- synchronized不能判断是否获取到锁;Lock可以判断
- synchronized可以自动释放锁(线程执行完同步代码块或者在执行中发生异常,就释放锁)。Lock是在finally中手动释放锁(unlock方法)
- synchronized:线程1获得锁的状态下如果阻塞,线程2会一直等待。但是Lock则不一定会一直等待
线程创建方式
1、继承Thread类
public class SaleTicket extends Thread
java是单继承,资源宝贵,要用接口方式。
2、new Thread
Thread t1 = new Thread();
t1.start();
3、实现runnable,并将runnable的实现类作为Thread的参数
public class MyRunnable implements Runnable {
@Override
public void run() {
// ...
}}
//0
public static void main(String[] args) {
MyRunnable instance = new MyRunnable();
Thread thread = new Thread(instance);
thread.start();}
4、实现callable,用futureTask封装,并作为Thread的参数
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());}
实现Runnable的方式
- 新建类实现runnable接口(不推荐)
public class MyRunnable implements Runnable {
@Override
public void run() {
// ...
}}
- 匿名内部类
new Thread(new Runnable(){
},"ThreadName").start();
没有创建新的类,直接new 接口
- 匿名内部类的lambda表达式写法
new Thread(() -> {
}, "your thread name").start();
更加简洁