线程与进程
进程是系统进行资源分配(文件、地址空间、IO等)和调度的基本单位。平时所说的一个运行的程序(已经被加载到内存中程序,是一个活动的实体)即可认为是一个进程;未被加载到内存中叫程序,只是硬盘上的一个静态文本而已。
线程作为独立运行和独立调度的基本单位,是进程的一个实体,即一条执行路径。它是由进程创建,共享进程所拥有的系统资源,没有单独的地址空间,但有自己的堆栈和局部变量。
简单来说,可以这么理解:
1. 进程拥有系统资源,除进程切换外,cpu执行线程而不是进程
2. 进程创建线程
3. 线程是具体执行逻辑,进程不直接执行
锁
一个对象拥有一把锁,不同对象之间的锁不同,互补干扰
synchronized()所传的参数为一个对象,或者一个类 。 程序运行到带synchronized关键字的代码块或方法会检查有没有其他线程获得所传入对象的锁,有则等待无则直接执行
例:
>
public class A {
public static void main(String[] args) {
B b = new B();
b.start();
System.out.println("A线程启动B线程");
synchronized (b) { //运行到这时才获取到B对象的锁,此时B线程处于等待状态
System.out.println("A同步");
try {
System.out.println("等待对象b完成计算......");
b.wait(); //运行到这时,释放对B的锁,然后进入等待状态
System.out.println("B wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b对象计算的总和是:" + b.total);
}
}
}
public class B extends Thread {
public int total;
@Override
public void run() {
System.out.println("B线程开始运行");
synchronized (this) {
System.out.println("B同步锁");//检查自己的锁是否被占用
for (int i = 0; i < 10; i++) {
total += i;
System.out.print(total+" ");
}
System.out.println("\nB计算完成");
notify();//唤醒A中main线程继续执行
}
}
}
运行结果:
第一种情况:
A线程启动B线程
B线程开始运行
A同步
等待对象b完成计算……
B同步锁
0 1 3 6 10 15 21 28 36 45
B计算完成 B wait b对象计算的总和是:45
第二种情况:
A线程启动B线程
A同步
等待对象b完成计算……
B线程开始运行
B同步锁
0 1 3 6 10 15 21 28 36 45
B计算完成
B wait
b对象计算的总和是:45
分析:
当A类中的main运行时,首先创建一个B线程并启动,当此时cpu分给b线程运行时,b检查自己所在进程是否被占用,由于main线程暂时未执行所以出现第二种情况;当cpu分配给main线程和b线程轮回执行时,会出现第一中情况
线程调度
线程调度是最大限度的影响多个线程间的执行次序,但不能决定次序
join( ):–线程合并–挂起当前线程,启动另一线程直到另一线程执行完在启动当前线程
wait( ):–线程暂停–强制暂停线程,直到notify或者notifyall方法被调用或者给wait方法指定等待时间且超时时使其进入可运行状态。此时线程若获取到锁,则放弃该锁
sleep( ):–线程休眠–使线程进入睡眠,但不会放弃已获取的锁,且超时时自动执行该进程
yield( ):–线程让步–暂停当前正在执行的线程对象让出cpu资源,该线程进入可运行状态,cpu下一个执行的线程是哪个无法确定,也有可能是当前线程。
线程池
线程池是指事先在创建一定数目的线程,当有新线程任务需求时,首先从线程池中取出一个线程给该任务使用,当任务结束时回收该线程以备为其他新任务请求线程时使用
//创建一个可重用的固定个数线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool( number)
//创建一个单任务线程池,该线程轮回使用
ExecutorService pool = Executors.newSingleThreadExecutor()
//创建一个可变个数的线程池,若任务需求线程数大于线程池中线程数则重现创建一个新的线程并加入线程池中,否则重用已创建的线程
ExecutorService pool = Executors.newCachedThreadPool();
//创建一个带延时功能的线程池
ScheduledExecutorService pool=Executors.newScheduledThreadPool(number);
pool.schedule( new thread(), delaytime, TimeUnit.MILLISECONDS);
//创建一个单认为延时线程池
ScheduledExecutorService pool =Executors.newSingleThreadScheduledExecutor();
//自定义线程池
ThreadPoolExecutor
有返回值的线程
实际上实现callable接口,该接口除带有返回指外其他功能类似于runnable接口
例:
class MyThread1 implements Callable<返回值类型>{
int total;
@Override
public Integer call() throws Exception {
//具体代码
return 返回值;
}