一 多线程的概念:
应用程序中,一个进程中有多个线程,每个线程有自己独立的内存空间(操作空间),彼此之间互相独立,多个线程执行多个任务。
在JAVA中的多线程其实是通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时,而是由java虚拟机调度轮流执行。
二 实现多线程的方法
某个类RunnableTest 实现接口 Runnable ,并实现方法
run()
例如
public class RunnableTest implements Runnable
{
public void run()
{
线程dosomething
}
}
//为线程执行的任务
Runnable runSomething = new RunnableTest ();
//创建线程,并绑定线程任务
Thread thread1 = new Thread(runSomething );
//启动Thread 线程
thread1.start();
三 线程的状态
线程状态总的可分为五大状态:分别是生、死、可运行、运行、等待/阻塞
1 新状态:线程对象已经创建,还没有在其上调用start()方法。
2 可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。
3 运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
4 等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态
5 死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
四 阻止线程执行
1 睡眠 Thread.sleep(时间),在睡眠时间后,线程进入可运行状态等待被运行,睡眠帮助所有线程获得运行机会的最好方法
2 线程的优先级和线程让步yield()
线程的让步是通过Thread.yield()来实现的。yield()方法的作用是:暂停当前正在执行的线程对象(转入可执行状态),并执行其他同级别优先级线程。优先级范围在1~10,默认5,设计多线程时,不可依赖优先级,因为优先级没有保障,只是作为一种提高程序效率的方法,setPriority() 设置优先级; 但是很多时间并不好用,可能线程会再次被线调度程序选中执行
3 中断线程join() ,等待其他线程执行完成才继续本线程
4 等待 wait(), 线程等待,直到被唤醒 notify 或者 notifyAll 再继续执行
5 线程终止 stop()
五 线程的同步与锁
目的;防止多线程执行某段代码时导致的数据异常,互相干扰
1 synchronized 单独使用于对象,使用对象锁
object lock;
synchronized lock;
public void run()
{
synchronized(lock){
do something;
}
}
Java中的每个对象都有一个监视器,来监测并发代码的重入,上面就synchronized获取了lock的监视器,
2 synchronized 用于方法,
public class Thread1 implements Runable{
public synchronized void run()
{
do something
}
}
其实是获取了Thread1的监视器,对象锁。
线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法。
六 线程池
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。
1 //创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
//关闭线程池
pool.shutdown();
2 //单任务线程池
线程数量为1的FixedThreadPool,如果提交了多个任务,
那么这些任务将会排队,每个任务都会在下一个任务开始之前运行结束,所有的任务将会使用相同的线程。
创建一个单线程的线程池。这个线程池只有一个核心线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
ExecutorService pool = Executors.newCachedThreadPool();
4 延迟线程池
//创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
//创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
//将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
//使用延迟执行风格的方法
pool.schedule(t4, 10, TimeUnit.MILLISECONDS);
pool.schedule(t5, 10, TimeUnit.MILLISECONDS);
5 单任务延迟线程池
/创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();
6 自定义线程池
//创建等待队列
BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
//创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
ThreadPoolExecutor pool = newThreadPoolExecutor(2,3,2,TimeUnit.MILLISECONDS,bqueue);
7 java 特征 锁 (lock,readLock,writeLock)
不同于同步synchronized所用监控器
//获取锁
Lock myLock;
中间放代码块,被锁定的代码块
//释放锁,否则别的线程没有机会执行了
myLock.unlock();
end