1.线程进程的区别
具体例子: 打开网易云,相当于打开一个进程, 点击播放音乐, 就相当于创建了一个线程, 点击下载, 相当于又创建了一个线程, 我们再去打开QQ, 就是又打开了一个进程, 总结: 线程是进程的子关系。
具体对比:
进程 | 线程 |
---|---|
资源分配的最小单位 | 系统调度的最小单位 |
有独立空间,相互之间是隔离的 | 没有独立空间, 同一个进程下的线程共享内存空间 |
一个进程有多个线程 | 一个线程隶属于一个进程 |
创建时消耗大,打开一个应用当然大 | 消耗小, 让操作系统去fork()一个线程 |
2.线程阻塞和等待的区别_什么导致线程阻塞?
阻塞: 指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)
调用sleep()方法后就会处于阻塞状态,不会释放cpu资源, 也不会释放锁,等时间到了, 又进入就绪状态。
等待: 和阻塞类似, 但是它会释放CPU, 释放锁, 调用wait()方法,等待用notify()和notifyAll()方法去唤醒它, 然后进入等待序列。
3.同步异步的区别
同步是所有的操作都做完,才返回给用户结果;即写完数据库之后,再响应用户,用户体验不好。而异步不用等所有操作都做完,就相应用户请求;即先响应用户请求,然后慢慢去写数据库,用户体验较好。”
4.JAVA创建线程的四种方式
继承Thread类创建线程
实现Runnable接口创建线程
使用Callable和Future创建线程
使用线程池例如用Executor框架
callable和future
public static class MyCallAble implements Callable{
int i = 0;
@Override
public Object call() throws Exception {
System.out.println(Thread.currentThread().getName() + ": i = " + (i++));
return i;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable callable = new MyCallAble();
for (int i = 0; i < 1000; i++) {
FutureTask futureTask = new FutureTask(callable);
new Thread(futureTask, "子线程" + i).run();
System.out.println(futureTask.get());
}
}
线程池的方法, 这里是线程池的构造函数
public ThreadPoolExecutor(int corePoolSize, //核心线程数
int maximumPoolSize, //线程池最大线程数
long keepAliveTime, //线程池空闲时线程的存活时长;
TimeUnit unit,//线程存活时长大单位,结合上个参数使用;
BlockingQueue<Runnable> workQueue) { //存放任务的队列,使用的是阻塞队列;
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
除了上面5个以外, 还有两个参数
threadFactory:线程池创建线程的工厂;
handler:在队列(workQueue)和线程池达到最大线程数(maximumPoolSize)均满时仍有任务的情况下的处理方式;
5.线程池的相关知识
线程池处理流程
4种拒绝策略
1.当触发拒绝策略时,只要线程池没有关闭,就由提交任务的当前线程处理(CallerRunsPolicy)
2.当触发拒绝策略时,直接抛出拒绝执行的异常,中止策略的意思也就是打断当前执行流程(AbortPolicy)
3.直接静悄悄的丢弃这个任务,不触发任何动作(DiscardPolicy)
4.如果线程池未关闭,就弹出队列头部的元素,然后尝试执行(DiscardOldestPolicy)
3大方法
public static void main(String[] args) {
// ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
// ExecutorService threadPool = Executors.newFixedThreadPool(5);//固定线程
ExecutorService threadPool = Executors.newCachedThreadPool();//固定线程
for (int i = 0; i < 100; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
threadPool.shutdown();
}
7大参数
public ThreadPoolExecutor(int corePoolSize, // 核心线程数量
int maximumPoolSize, //最大线程数量
long keepAliveTime, //超过这个时间没人调用就释放
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, //线程工厂
RejectedExecutionHandler handler//拒绝策略
) {
this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
this.mainLock = new ReentrantLock();
this.workers = new HashSet();
this.termination = this.mainLock.newCondition();
if (corePoolSize >= 0 && maximumPoolSize > 0 && maximumPoolSize >= corePoolSize && keepAliveTime >= 0L) {
if (workQueue != null && threadFactory != null && handler != null) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
} else {
throw new NullPointerException();
}
} else {
throw new IllegalArgumentException();
}
}
6.sleep(), wait(), jion(), yield()
sleep(): 进入阻塞状态, 但是不释放锁和cpu资源, 等待时间到了又进入就绪状态
wait(): 释放锁和cpu资源, 等待notify和notifyAll唤醒进入等待队列。
jion(): 如t.jion(), 代表主线程将执行权交给t, t执行完了以后在继续执行
yield():释放cpu但不释放执行权。