java的多线程机制上
2015-07-03 22:36
323 查看
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
一、多线程概述
package com.laobi.day12; public class ThreadTest01 { /** * 进程:正在进行中的程序(直译) * * 线程:就是进程中一个程序执行的控制单元(执行路径) * 一个进程中可以多执行路径,称之为多线程 * * 一个进程中至少要有一个线程 * * 开启多个线程是为了同时运行多部分代码 * * 每一个线程都有自己运行的内容。这个内容可以称为线程要执行的任务 * * 多线程的好处:解决了多部分同时运行的问题 * 多线程的弊端:线程太多会导致效率的降低 * * 其实应用程序的执行都是cpu在做着快速的切换完成的。这个切换时随机的。 * * jvn启动时就启动了多个线程,至少有两个线程可以分析出来的 * 1、执行main函数的线程 * 该线程的任务代码都定义在main函数中 * 2、负责垃圾回收的线程 * * * @param artcool */ public static void main(String[] args) { Demo d1 = new Demo("旺财"); //主线程运行示例 Demo d2 = new Demo("小强"); d1.show(); d2.show(); // new Demo(); jvm线程演示 // System.gc(); System.out.println("diu"); } } class Demo { private String name; public Demo(String name) { super(); this.name = name; } public void show() { for(int x=0;x<10;x++) { for(int y=0;y<999999999;y++){} System.out.println("demo 走"+name+"..."+x); } } }
二、创建线程
package com.laobi.day12; public class ThreadTest02 { /** * 如何创建一个线程呢? * 创建线程方式一:继承Thread类 * * 步骤: * 1、定义一个类继承Thread类。 * * 2、覆盖Thread类中的run方法。 * * 3、直接创建Thread的子类对象 * 4、调用start方法开启线程并调用线程的任务run方法执行 * * 可以通过Thread的getName获取线程的名称 Thread——编号 * * 主线程的名字就是main * @param args */ public static void main(String[] args) { /*创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行 而运行的指定代码就是这个执行路径的主任务 jvm创建的主线程的任务都定义在了主函数中 而自定义的线程它的任务在哪? Thread类用于描述线程,线程是需要任务的。所以Thread类也对任务的描述 这个任务就是通过Thread类中的run方法来体现。也就是说,run方法就是封装自定义线程运行任务的函数 run方法中定义就是线程要运行的代码任务 开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法 */ // Thread t1 = new Thread(); Demo2 d1 = new Demo2("jack"); Demo2 d2 = new Demo2("tom"); d1.start(); d2.start(); } } class Demo2 extends Thread { private String name; Demo2(String name) { this.name = name; } public void run() { show(); } public void show() { for(int x=0;x<10;x++) { for(int y=0;y<999999;y++) { } System.out.println(name+"...."+x+"..."+Thread.currentThread().getName()); } } }
三、Thread类的基本获取和设置方法
1)获取线程名字
Thread类中方法 String getName()
在一个不是Thread子类中获取名字:
Thread类中静态方法
static Thread currentThread()
返回正在运行的,当前线程对象 Thread类对象
继续使用线程对象的 getName()获取线程的名字
Thread类的方法 void setName(String name)设置线程名
Thread(String name) 用的是Thread类构造方法
子类使用super访问父类构造器
在Thread子类中,获取线程名字,直接使用父类方法getName()
在不是Thread子类中,通用代码,Thread.currentThread().getName()
四、线程的优先级的获取和设置
Thread类方法getPriority() 获取到优先级
Thread类方法setPriority(int t) 设置优先级
package com.test.xiancheng; public class Test07 { /** *线程的生命周期及状态转换 *1、新建状态(new) * 创建一个线程对象后,该线程对象就处于新建状态,此时它不能运行,和其他Java对象 * 一样,仅仅由Java虚拟机为其分配了内存,没有表现出任何线程的动态特征 *2、就绪状态(runnable) * 当线程对象调用了Start()方法后,线程就进入就绪状态了。 * 此时它只是具备了运行条件,能否获得cpu的使用权开始运行,还需要等待系统的调度 *3、运行状态(running) * 如果出就绪状态的线程获得了cpu的使用权,开始执行run()方法中的线程执行体,则该线程处于运行状态。 *4、阻塞状态(blocked) * 一个正在执行的线程在某些特殊情况下,如执行耗时的输入/输出操作时,会放弃cpu使用权,进入阻塞状态。 * 阻塞就不能进入阻塞状态后,就不能进入排队队列。 * 例举一下线程由运行状态转换成阻塞状态的原因 * a、当线程试图获取某个对象的同步锁时,如果该锁被其他线程所持有,则当前线程会进入阻塞状态, * 如果想从阻塞状态进入就绪状态必须获得其他线程所持有的锁 * b、当线程调用了一个阻塞式的io方法时,该线程就会进入阻塞状态,如果想进入就绪状态就必须要等到这个阻塞的 * io方法返回 * c、当线程调用了某个对象的wait()时,也会使线程进入阻塞状态,如果想进入就绪状态就需要使用 * notify()方法唤醒该线程 * d、当线程调用了Thread的sleep(long mills)方法时,也会使线程进入阻塞状态,在这种情况下 * 只需等到线程的睡眠时间到了以后,线程就会自动进入就绪状态 * f、当在一个线程中调用另一个线程的join()方法时,会使当前线程进入阻塞状态,在这种情况下,需要等到 * 需要等到新加入的线程运行结束后才会结束阻塞状态,进入就绪状态 * 线程从阻塞状态只能进入就绪状态 *5、死亡状态(Terminated) * 线程的run()方法正常执行完毕或者线程抛出一个未捕获的异常(Exception)、错误(Error),线程 * 就会进入死亡状态。一旦进入死亡状态I,线程将不再拥有运行的资格,也不能再转换到其他状态 * * *线程的调度:分别是分时调度模型和抢占式调度模型 *分时调度:让所用的线程轮流获得cpu的使用权,并且平均分配cpu的时间片 *抢占式调度:让可运行池中优先级高的线程优先占用cpu,而对优先级相同的 * 线程,随机选择一个线程占用cpu,当它失去cpu的使用权后, * 再随机选择其他线程获取cpu使用权。 *1、线程的优先级: * 如果需要对线程进行调度,最直接的方式就是设置线程的优先级 *2、线程休眠: * 使正在执行的线程暂停,将cpu让给别的线程,这是可以使用sleep(),该方法可以让当前正在执行 * 的线程暂停一段时间,进入休眠等待状态。 *3、线程让步: * 可以通过yield()方法来实现,该方法和sleep有点相似,都可以让正在运行的线程暂停, * 区别在于yield()方法不会阻塞线程,他只是将线程转换成就绪状态,让系统调度器重新调度一次 *4、线程插队: * 当在某个线程中调用其他线程的join()方法时,调用的线程将被阻塞,直到 * 被join()方法加入的线程执行完成后他才会继续运行 * * * 多线程同步: * 1、线程安全 * 2、线程同步方法 * 3、同步方法:当把共享资源的操作放在synchronized定义的区域内时,便为这些操作加了同步锁 * 在方法前面同样可以使用synchronized关键字来修饰,被修饰的方法为同步方法,它能实现 * 和同步代码块同样的功能。被synchronized修饰的方法在某一时刻只允许一个线程访问 * ,访问该方法的其他线程都会被阻塞,直到当前线程访问完毕后,其他线程才有机会执行方法 * */ public static void main(String[] args) { Thread minPriorty = new Thread(new MinProirty(),"优先级较低的线程"); Thread maxPriorty = new Thread(new MaxPriorty(),"优先级较高的线程"); minPriorty.setPriority(Thread.MIN_PRIORITY); maxPriorty.setPriority(10); maxPriorty.start(); minPriorty.start(); } } class MaxPriorty implements Runnable { public void run() { for(int i=0;i<=10;i++) { System.out.println(Thread.currentThread().getName()+"正在输出:"+i); } } } class MinProirty implements Runnable { public void run() { for(int i=0;i<=10;i++) { System.out.println(Thread.currentThread().getName()+"正在输出:"+i); } } }
五、线程休眠
package com.test.xiancheng; public class XCxiumian { /** * 线程休眠: * 使正在执行的线程暂停,将cpu让给别的线程,这是可以使用sleep(),该方法可以让当前正在执行 * 的线程暂停一段时间,进入休眠等待状态。 * @throws Exception */ public static void main(String[] args) throws Exception { new Thread(new SleepThread()).start(); for(int i=1;i<=10;i++) { if(i==5) { Thread.sleep(2000); } System.out.println("主线程正在输出:"+i); Thread.sleep(500); } } } class SleepThread implements Runnable { public void run() { for(int i=1;i<=10;i++) { if(i==3) { try { Thread.sleep(2000); } catch(InterruptedException e) { e.printStackTrace(); } } System.out.println("线程一正在输出:"+i); try { Thread.sleep(500); } catch(Exception e) { e.printStackTrace(); } } } }
五、线程让步
package com.test.xiancheng; public class XCrangbu { /** * 线程让步: * 可以通过yield()方法来实现,该方法和sleep有点相似,都可以让正在运行的线程暂停, * 区别在于yield()方法不会阻塞线程,他只是将线程转换成就绪状态,让系统调度器重新调度一次 * */ public static void main(String[] args) { Thread t1 = new YieldThread("线程A"); Thread t2 = new YieldThread("线程B"); t1.start(); t2.start(); } } class YieldThread extends Thread { public YieldThread(String name) { super(name); } public void run() { for(int i=0;i<5;i++) { System.out.println(Thread.currentThread().getName()+"----"+i); if(i==3) { System.out.print("线程让步:"); Thread.yield();//线程运行到此,做出让步 } } } }
六、线程插队
package com.test.xiancheng; public class XCchadui { public static void main(String[] args) throws Exception { Thread t = new Thread(new EmergencyThread(),"线程一"); t.start(); for(int i=1;i<6;i++) { System.out.println(Thread.currentThread().getName()+"输入:"+i); if(i==2) { t.join(); } Thread.sleep(500); } } } class EmergencyThread implements Runnable { public void run() { for(int i=1;i<6;i++) { System.out.println(Thread.currentThread().getName()+"输入:"+i); try { Thread.sleep(500); } catch(InterruptedException e) { e.printStackTrace(); } } } }
相关文章推荐
- java&postgresql时区总结
- java&postgresql时区总结
- SpringMVC使用hibrenate validation进行验证
- [Java入学测试] 技术博客书写规则
- 2015070301 - EffactiveJava笔记 - 第52条 通过接口引用对象(1)
- java学习09--选择结构-switch练习、if和Switch使用比较
- JavaSE笔记之<泛型再理解(简化版)>
- 贪吃蛇小游戏java实现代码分析
- 什么是java程序的打包???
- 异常类型 && spring事务回滚
- java学习09--选择结构-switch语句
- web2.0之servlet
- 【Spring异常系列】LogFactory缺失
- scrapy学习笔记——第一个项目,eclipse+pydev搭建scarpy项目
- Java集合中对象排序
- javaSE学习笔记之面向对象程序设计(一)
- java方法的遗留问题:
- java也支持重载!
- Spring 从零开始-01
- Java中 equals 和 == 区别