1 一个程序至少有一个进程,一个进程至少有一个线程.
2 并发性:同一时刻 只有一条指令执行 多个进程指令被快速的轮转的执行 ,表面上:多个进程同时执行。总之并发与进程有关
并行性:同一时刻,多条指令 在多个处理机上同时执行。
二 线程的创建和启动
第一种通过继承Thread类来创建线程类
public class FirstThread extends Thread{
public void run (){
}
public static void main(String[] args) {
new FirstThread().start();
}
}
创建:run函数
启动:对象的start
4 一个程序中线程的数字,这其中包括了程序的主线程。不要忘了
5 getName()函数返回调用改方法的线程的名字
Thread.currentThread()返回当前正在执行的线程对象。
6 使用继承thread类,会导致多个线程之间无法共享线程类的实例变量。。。什么意思呢
第二种实现runnable接口来创建线程类
public class SecondThread implements Runnable{
public void run (){
System.out.println(Thread.currentThread().getName());//只能用Thread这种方法来获取线程的名字对于第一种方法两种是都可以的
}
public static void main(String[] args) {
SecondThread st = new SecondThread();
new Thread(st,"nihao").start();
}
}
第三种:使用Callable和Future创建线程
(未看)
三线程的生命周期
1五种状态:new,runnable(就绪),运行(running),阻塞(blocked),死亡(dead)
2启用线程的方法不能调用run方法,一定是调用start方法。
3只能对处于新建状态的线程调用start()方法。否则将引发非法线程调用错误
四 控制线程
1join方法
thread提供了一个让线程等待另一个线程完成的方法join()方法:a线程调用了B线程的join方法,那么只有b的run方法执行完毕后才会继续向下推进。
具体的方法join()
join(5000) 等待这个线程执行的时间最长为5000毫秒
2后台线程
他是在后台运行的,他的任务是为其他的线程提供服务。如果前台的进程都死亡,那么后台线程也死亡。
Daemon d = new DaemonThread();
d.setDaemon(ture);
d.start();//必须首先设置为后台线程,才能start
3线程睡眠
让线程暂停,进入阻塞状态
Thread.sleep(1000);睡眠1000毫秒/写在run方法中,以此类推,凡是这种特殊形式的都写在main方法中
4线程让步
Thread.yield();
只有优先级与当前的线程相同,或者优先级比当前线程的优先级要高且准备就绪的线程才会进入获得执行的机会,因此需要设置优先级
5改变线程的优先级
具体的方法:serPriority(int newPriority) getPriority(),其中第一个方法的参数的范围是1-10
静态的值的参数MAX_PRIORITY 10
nomal 5
min 1
五:线程同步
线程的安全问题:当两个进程并发的修改同一个文件就有可能造成异常
1 同步代码块:java使用同步监视器也就是同步代码块,也就是,线程开始执行同步代码块之前,必须先获得同步监视器的锁定。
/**
写在run方法中,对于线程来说,如果不知道代码往哪里写就写在run方法中
*/
syschronized(obj){ //obj就是同步监视器
}
任何时刻只有一个进程可以获得对同步监视气的锁定。执行完了会自定释放对同步监视器的锁定
2同步方法 就是使用 syschronized来修饰某个方法
3 同步锁
具体的方法
public void draw (){
lock.lock;
try {
}
finally
{
lock.unluck;
}
}
六:线程通信:
1 传统的线程通信:
wait()导致当前线程等待,直到其他线程调用同步监视器的notify()方法后者notifyall()方法来唤醒该线程
notify () 唤醒在此同步监视器上等待的单个线程
notifyall()唤醒在此同步监视器上等待的所有线程
2 使用conditon控制线程通信,
3使用BlockingQueue控制线程通信
七:线程组和未处理的异常
八:线程池:
使用线程池来执行线程任务的步骤,
ExecutorService pool = Executors.newFixedThreadPool(6);
pool.submit(new XXXThread());
pool.submit(new XXXthread());
pool.shutdown();
线程池ThreadPoolExecutor继承自ExecutorService。是jdk1.5加入的新特性,将提交执行的任务在内部线程池中的可用线程中执行。
构造函数
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize 线程池维护的核心线程数。为什么这里说核心线程数而不是最小线程数是因为在线程池被创建后,并不会直接创建corePoolSize个线程,而是等任务到来时临时创建。等按照需要创建了corePoolSize个线程之后,这些数量的线程即使闲置,也不会被线程池收回。这时即可以将这个值理解为线程池维护的最小线程数了。
maximumPoolSize 线程池维护的最大线程数。
keepAliveTime 当线程池中的线程数量大于corePoolSize,多出那部分数量的线程空闲keepAliveTime后会被收回。
unit keepAliveTime的时间单位。可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
workQueue 存放通过execute方法提交给线程等待执行的任务的队列。
threadFactory 负责给线程池创建线程的工厂。
handler 在当队列达到极限导致任务执行阻塞时执行的处理策略。handler有四个选择:ThreadPoolExecutor.AbortPolicy(抛出java.util.concurrent.RejectedExecutionException异常)。ThreadPoolExecutor.CallerRunsPolicy(重试添加当前的任务,他会自动重复调用execute方法)。ThreadPoolExecutor.DiscardOldestPolicy(抛弃旧的任务)。
ThreadPoolExecutor.DiscardPolicy(抛弃当前的任务)。
对于一般的应用,我们不用通过构造函数来创建线程池,而是用一些封装过的工具方法,这些方法设置了大多数参数的缺省值。只有对线程池的特性有更高的要求时,才直接使用构造函数。
Executors.newCachedThreadPool(创建自动增加或减少容量的线程池)
Executors.newFixedThreadPool(创建固定容量的线程池)
Executors.newSingleThreadExecutor(单独线程的线程池)。
1:提高效率 创建好一定数量的线程放在池中,等需要使用的时候就从池中拿一个,这要比需要的时候创建一个线程对象要快的多。 2:方便管理 可以编写线程池管理代码对池中的线程统一进行管理,比如说系统启动时由该程序创建100个线程,每当有请求的时候,就分配一个线程去工作, 如果刚好并发有101个请求,那多出的这一个请求可以排队等候,避免因无休止的创建线程导致系统崩溃
流程分析:线程池的主要工作流程如下图:

169万+

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



