多线程基础
1、 多线程的实现方法及特点:
1.1.1 继承Thread类
/** * Thread类的特点 * @author heshan * */ 2 publicclass Threadtest extends Thread { 3 //继承Thread的类每次都要创建一个新的对象,所以无法共享该实例变量 4 privateinti; 5 //线程执行体 6 publicvoid run() { 7 for(;i<100;i++){ 8 System.out.println("Thread Name:"+getName()+" "+i); 9 } 10 } 11 publicstaticvoid main(String[] args){ 12 Threadtest t=new Threadtest(); 13 //主线程和子线程并行执行 14 t.start(); 15 System.out.println("main:"+Thread.currentThread().getName()); 16 //Thread.currentThread(),该方法返回当前正在执行的线程对象 17 for(inti=0;i<100;i++){ 18 System.out.println(Thread.currentThread().getName()+" "+i); 19 if(i==20){ 20 //getName()返回调用该法的线程名字 21 Threadtest t1=new Threadtest(); 22 // setPriority(MAX_PRIORITY),改变优先级 23 t1.setPriority(PriorityMAX_PRIORITY); 24 t1.start();//启动线程 25 new Threadtest().start(); 26 } 27 } 28 29 } 30 } 31 |
1.1.2实现Runnable接口
/** * Runnable接口特点 * @author heshan * Runnable的实现类的实例作为Thread的target来创建Thread对象 */ public class RunnableTest implements Runnable{ //采用Runnable接口的方式创建的多个线程可以共享线程类的实例变量 private int i; public void run() { for(;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args){ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i==20){ RunnableTest r1=new RunnableTest(); Thread t=new Thread(r1,"新线程1"); //setPriority()改变线程的优先级 t.setPriority(5); t.start(); Thread t2=new Thread(r1,"新线程2"); t2.setPriority(9); t2.start(); } } }
} |
2、线程的生命周期:
/**
* 线程的生命周期:
* 新建(New):仅仅由java 虚拟机为其分配内存,并初始化其成员变量的值
* 程序不会执行线程的线程执行体。
* 就绪(Runnable):该线程处于就绪状态,java虚拟机为其创建方法调用
* 栈和程序计数器,只是表示该线程可以运行了,何时运行
* 取决于jvm里线程调度器的调度。
* 运行(Running):开始执行 run()方法的线程执行体,则该线程处于
* 运行状态。
* 抢占式策略的系统----会给每个可执行的线程一个小时间段
* 来处理任务,系统会考虑线程的优先级。
* 协作式调度策略----只有当一个线程调用了它的 sleep(),
* yield()方法后才会放弃所占用的资源。
* 阻塞(Blocked) 线程从阻塞状态只能进入就绪状态,不能直接进入运行状态。
死亡(Dead)死亡的线程不能再 调用start()启动。
*/
3、线程控制:
join线程 ---当在某个程序执行流中调用其他线程的join()方法时,调 用线程将被阻塞,直到被join()方法加入的线程执行完为止。 后台线程 ---- 在后台运行的线程,它的任务是为其他的线程提供服务,所有的前台 线程都死亡,后台线程自动死亡。 线程睡眠sleep ---让当前正在执行的线程暂停一段时间,并进入阻塞状态。sleep() * 是Thread的静态方法。 线程让步 ---yield是Thread的静态方法,它可以让当前正在执行的线程暂停,但它 不会阻塞该线程,只是将该线程转入就绪状态。当某个线程调用了yield() 方法暂停之后,线程调度器又将其调度出来重新执行。 改变线程优先级 ---setPriority() * MAX_PRIORITY: 10 * MIN_PRIORITY: 1 * NORM_PRIORITY:5 */ |
4、线程同步
线程安全问题 ---当多个线程修改同一个共享数据时,将涉及数据安全问题 同步代码块 ---synchronized(obj){ * 同步代码块 * } * obj就是同步监视器(通常使用可能并发访问的共享资源) * 任何时刻只能有一个线程可以获得同步监视器的锁定,当同步代码块执行 * 完成后,该线程会释放对该同步监视器的锁定。 同步方法 --- 使用synchronized 关键字来修饰某个方法,同步方法的同步监视器 * 时This,也就是调用该方法的对象。 释放同步监视器的锁定 ---任何线程进入同步代码块、同步方法之前,必须获得对同步 * 监视器的锁定。 释放锁定 1、同步方法,同步代码块执行结束或者遇到 break、return终止了 * 该方法的继续执行。 * 2、同步代码块、同步方法中出现了未处理的Erroe或Exception * 3、程序执行了同步监视器对象的wait()方法,则当前线程暂停, * 并释放同步监视器。****sleep(),yield()不会释放同步监视器 同步锁(Lock) ---同步锁由Lock对象充当 Lock、ReadWriteLock时两个根接口 Lock的实现类ReentrantLock ReadWriteLock的实现类为 ReentrantReadWriteLock * lock获取多个锁时,必须以相反的顺序释放。 死锁 ---当两个线程相互等待对方释放同步监视器时就会发生死锁。---不需多解释--- * wait() 当前线程暂停并释放同步监视器 notify() 唤醒在此同步监视器上等待的单个线程-----只有当前线程放弃对该同步监视器的锁定后才执行被唤醒的线程。 * notifyAll() 唤醒所有在此同步监视器上等待的线程只有当前线程放弃对该 同步监视器的锁定后才执行被唤醒的线程。 */ |
5、线程池
newCachedThreadPool()---创建一个具有缓存功能的线程池。 newFixedThreadPool(int n) ---创建一个可重用的、具有固定数量的线程池。 newSingleThreadExecutor()---创建一个可重用的线程池。 newScheduledThreadPool(int corePoolSize)---创建制定数量的线程池,可以指定延迟后执行线程任务 newSingleThreadScheduledExecutor()---创建只有一个线程的线程池,它可以在指定延迟后加载 ExecutorService newWorkStealingPool()---创建有足够的线程的线程池来支持给定的 ForkJoinPool()--- */ |