目录
sleep()、join()、yield()、wait()的区别:
synchronized 和java.util.concurrent.locks.Lock的异同:
多线程:
进程:
活动的程序,即正在使用的程序;每个进程拥有独立的内存空间
线程:
是进程中最小的调度单元;是cpu控制的最小的执行单元; 轻量级的线程
并发:
在同一时间间隔内,同时有多个线程运行
并行:
在同一时刻,同时有多个线程运行
创建线程的三大方法:
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
区别:
Thread类:重写run()方法,简单,受限于Java单继承
runnable接口:重写run()方法,实现多个接口,实现资源的共享
callable接口:重写call()可方法,以获取线程的返回值,配合FutureTask类
Thread类
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class Test {
public static void main(String[] args) {
Thread thread1 = new MyThread();
thread1.start();
System.out.println(Thread.currentThread().getName());
}
}
Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
}
}
public class Test {
public static void main(String[] args) {
//创建实例
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
System.out.println(Thread.currentThread().getName()+"正在执行");
}
}
Callable接口
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+"正在执行");
return Thread.currentThread().getName();
}
}
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建实例
MyCallable myCallable = new MyCallable();
FutureTask<String> task = new FutureTask<>(myCallable);
Thread thread = new Thread(task);
thread.start();
//获取返回值
String result = task.get();
System.out.println(result);
System.out.println(Thread.currentThread().getName()+"正在执行");
}
}
Thread类API:
方法 | 描述 |
---|---|
public static Thread currentThread() | 返回当前的线程 |
public final String getName() | 返回线程名称 |
public final void setPriority(int priority) | 设置线程优先级 |
public void start() | 开始执行线程 |
public static void sleep(long m) | 使目前的线程休眠m秒 |
public final void yield() | 暂停目前的线程,运行其他线程 |
public void run() | 线程要执行的任务 |
sleep()、join()、yield()、wait()的区别:
sleep():线程休眠,是Thread类中的方法,会让当前线程处于阻塞状态,指定时间过后,自动唤醒,线程就绪状态
join():是Thread类中的方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态
yield():线程礼让,是Thread类中的方法,暂停当前正在执行的线程对象,让出时间片,变成就绪状态,再和其他线程抢时间片
wait():是Object类中的方法,用在同步锁的代码中,作用:线程等待(挂起,阻塞),释放锁,需要手动唤醒
线程状态:
1.新建状态
new 线程对象
2.就绪状态
调用了 对象.start()方法
3.运行状态
抢占了cpu的时间片
4.阻塞状态
调用sleep()、join()、wait()方法
5.死亡状态
线程执行完或者因异常退出run()方法,结束生命周期
线程同步:
好处:解决了线程同步的数据安全问题
弊端:当线程很多的时候,每个线程都会去判断同步上面的这个锁,很耗费资源,降低效率
实现同步的两大方式:
1.基于synchronized(同步)实现
同步语句块
synchronized(线程共享对象){同步代码块}
同步实例方法
修饰符 synchronized 返回值类型 方法名 [参数列表]{方法体}
静态同步方法
修饰符 synchronized static 返回值类型 方法名 [参数列表]{方法体}
2.基于Lock实现
private Lock lock = new ReentrantLock();//ReentrantLock()可重入锁
synchronized 和java.util.concurrent.locks.Lock的异同:
相同点:用来实现同步
不同点:
synchronized:关键字,同步代码块,同步实例方法,同步静态方法,自动解锁,jdk1.6在之后对synchronized进行了优化,性能得到了提升。
Lock:接口,提供的有各种实现类,手动的加锁和解锁,使用try和finally,性能更好,灵活性更高
死锁:
当多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,从而导致两个或者多个线程都在等待对方释放资源,都停止执行的情况。(如,哲学家就餐问题)
线程通信:
共享变量,同步锁
1、使用锁对象的wait()/notify()/notifyAll()方法
2、Lock中的await()/signal()/signalAll()方法
生产者与消费者模式
线程池:
创建的一些线程的集合,称为线程池
线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后再需要执行新的任务时重用这些线程而不是新建线程
创建线程池:
public ThreadPoolExecutor(int corePoolSize,//核心线程数,一般为cpu内核+1
int maximumPoolSize,//最大线程数量
long keepAliveTime,//当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
TimeUnit unit,//存活时间的单位
BlockingQueue<Runnable> workQueue,//存放任务的队列
RejectedExecutionHandler handler//超出线程范围和队列容量的任务的处理程序 )
获取线程池对象:
通过Executor工厂类中的静态方法
1.newCachedThreadPool
特点:创建一个默认的线程池对象,里面的线程可重用,且在第一次使用时才创建
2.newFixedThreadPool
特点:可指定创建线程数,并且可以重复用
3.newSingleThreadExecutor
特点:只会创建一个线程
工作流程:
1.先提交任务,判断核心线程是否已满,如果未满,创建核心线程处理任务;如果已满进入第二步
2.再判断阻塞队列是否已满,如果未满,将任务放入队列,继续等待;如果已满进入第三步
3.判断线程池最大数量,如果未满,则创建线程执行任务;如果已满,则按照拒绝策略处理