线程和进程的区别
进程是程序的一次执行过程,是程序在执行过程中的分配和管理资源的基本单位,每个进程都有自己的进程空间;线程是CPU调度和分派的基本单位,线程是进程的一部分,一个进程可以有多个线程,但线程只能存在于一个进程中
进程和线程的形象比喻
线程的生命周期
线程至少有5种状态:初始态,执行态,等待态,就绪态,终止态
Java线程切换及其状态

死锁
多个线程同时被阻塞,它们中的一个或者很多个都在等待某个资源被释放,由于线程被无限期地阻塞,因此线程不可能正常终止
产生死锁的四个必要条件
互斥条件
请求和保持条件
不剥夺条件
循环等待条件
创建多线程的四种方法
继承 thread类
实现runnable接口
实现callable接口
线程池
Callable接口和FutureTask
创建一个实现callable的实现类,重写call方法
创建一个callable实现类的对象
将callable实现类的对象作为参数,传递给futuretask的构造器,创建FutureTask的对象
将FutureTask的对象作为参数再传递给thread类的构造器,创建thread对象,并启动
通过futuretask类的对象调用方法get获取线程中的返回值
package com.chen.ThreadTest;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class NumThread implements Callable{
private int sum=0;
@Override
public Object call() throws Exception {
for (int i = 0; i <100; i++) {
if(i%2==0){
System.out.println(Thread.currentThread().getName() + ":" + i);
sum+=i;
}
}
return sum;
}
}
public class ThreadNew {
public static void main(String[] args) {
NumThread numThread = new NumThread();
FutureTask futureTask = new FutureTask(numThread);
Thread thread = new Thread(futureTask);
thread.setName("线程一");
thread.start();
try {
Object o = futureTask.get();
System.out.println(Thread.currentThread().getName() + ":" + o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
线程池
为什么要使用线程池
降低资源消耗 通过重复利用已经建立的线程来降低线程创建和销毁造成的消耗
提高响应速度 当任务到达时,任务可以不需要等待线程创建就能立即执行
提高线程的可管理性 线程时稀缺资源 如果无限制的创建,不仅会消系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控
四种线程池
newCachedThreadPool 缓存线程池
public static ExecutorService newCachedThreadPool()
先检查这个线程池有没有闲置的线程,如果有就把这个新任务加到这个线程中来,如果没有,就新建一个线程加入线程池并执行新任务
闲置的默认时间是60s,超过60s,这个线程就会被销毁
newFixedThreadPool 核心线程池
public static ExecutorService newFixedThreadPool(int corePoolSize);
和缓存线程池的原理是一样的,只是参数不一样,线程池中的线程数是指定的
newSchedualThreadPool 调度线程池
public static ScheduledExecutorService new ScheduledThreadPool(int corePoolSize)
该线程池内的线程可以推迟执行或者周期执行
newSingleThreadExecuor 单例线程池
public static ExecutorService newSingleThreadExecutor();
单例线程池,只含有一个线程
推荐的创建线程池的方法
public ThreadPoolExecutor(int corePoolSize,//线程池的核心线程数量
int maximumPoolSize,//线程池的最大线程数
long keepAliveTime,//当线程数大于核心线程数时,多余的空闲线程存活的最长时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列,用来储存等待执行任务的队列
ThreadFactory threadFactory,//线程工厂,用来创建线程,一般默认即可
RejectedExecutionHandler handler//拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务
)
当线程数量小于核心线程数时,新建线程
当线程数量大于等于核心线程数,任务队列没有满的时候,加入任务队列
当任务队列满时,若小于最大线程数,新建线程;当大于最大线程数时,按照饱和策略进行处理

饱和策略
AbortPolicy 直接抛出异常
CallerRunsPolicy 用调用者所在的线程来执行任务; (当前调用者线程执行任务完成后,再执行此任务)
DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
DiscardPolicy:直接丢弃任务
示例代码
package com.chen.ThreadTest;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorDemo {
private static final int CORE_POOL_SIZE = 5;
private static final int MAX_POOL_SIZE = 10;
private static final int QUEUE_CAPACITY = 100;
private static final Long KEEP_ALIVE_TIME = 1L;
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(QUEUE_CAPACITY),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i = 0; i < 10; i++) {
Runnable worker=new MyRunnable(""+i);
executor.execute(worker);
}
executor.shutdown();
}
}
sleep,wait,yield,join
sleep和wait的区别
sleep是线程thread的方法,而wait是object的方法
sleep不会释放锁,但是会让出cpu资源,wait会释放锁
thread.sleep在任何情况下都能执行,object.wait必须在synchronized代码块中执行
yield和join
A.yield() 释放cpu资源,使A从运行中转为可运行状态,然后A和B同时去竞争这个资源,所以当A.yield之后,下一个执行的也有可能是A
A.join() 则会插队B线程,直到A线程执行完毕,才轮到B(阻塞状态)
synchronized关键字
synchronize关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能由一个线程执行
谈谈synchronized和ReentrantLock的区别
synchronized 自动释放锁,而lock需要手动释放锁,synchronized依赖于jvm而lock依赖于api
volatile关键字
volatile关键字的主要作用就是保证变量的可见性(一个线程对共享变量进行了修改,那么另外的线程都是立即可以看到修改后的最新值),然后还要一个作用就是防止指令进行重排序优化
谈谈synchronized和volatile关键字的区别
volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块
volatile关键字能保证数据的可见性,但不能保证数据的原子性
volatile关键字主要用于解决变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性
ThreadLocal
实现每个线程都有自己的专属本地变量
6267

被折叠的 条评论
为什么被折叠?



