java多线程学习笔记
1、继承Thread
package com.thread; class ThreadTest extends Thread { private String name; public ThreadTest(String name){ this.name = name; } public void run(){ for(int i=0; i<10; i++){ System.out.println(name + "运行:" + i); try { sleep((int) Math.random() * 10); } catch (Exception e) { e.printStackTrace(); } } } } public class Thread1{ public static void main(String[] args) { ThreadTest tt1 = new ThreadTest("A"); ThreadTest tt2 = new ThreadTest("B"); tt1.start(); tt2.start(); } }
2、实现Runnable
package com.thread; class RunnableTest implements Runnable { private String name; public RunnableTest(String name){ this.name = name; } public void run(){ for(int i=0; i<10; i++){ System.out.println(name + "运行:" + i); try { Thread.sleep((int) Math.random() * 10); } catch (Exception e) { e.printStackTrace(); } } } } public class Thread2{ public static void main(String[] args) { new Thread(new RunnableTest("C")).start(); new Thread(new RunnableTest("D")).start(); } }
备注:Thread类和Runnable接口的关系
Thread2类通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个约定。所有的多线程代码都在run方法里面。Thread类实际上也是实现了Runnable接口的类。
在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。
3、join()方法的使用
package com.thread; /** * join():指等待t线程终止。 * * 使用方式: * join是Thread类的一个方法,启动线程后直接调用,即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。 * 也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。 * * 为什么要用join()方法? * 在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后, * 需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。 * * @author Administrator */ class MainTest extends Thread { private String name; public MainTest(String name){ this.name = name; } public void run(){ System.out.println(Thread.currentThread().getName()+"子线程运行开始!"); for(int i=0; i<10; i++){ System.out.println("子线程"+name + "运行 : " + i); try { Thread.sleep((int) Math.random() * 10); } catch (Exception e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"子线程运行结束!"); } } public class Thread3{ public static void main(String[] args) { System.out.println(Thread.currentThread().getName()+"主线程运行开始!"); MainTest mt1 = new MainTest("A"); MainTest mt2 = new MainTest("B"); mt1.start(); mt2.start(); /** * join():指等待t线程终止。 * 等子线程执(mt1和mt2)行完再返回 */ try { mt1.join(); mt2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"主线程运行结束!"); } }
运行结果:
main主线程运行开始! Thread-0子线程运行开始! 子线程A运行 : 0 Thread-1子线程运行开始! 子线程B运行 : 0 子线程A运行 : 1 子线程B运行 : 1 子线程A运行 : 2 子线程B运行 : 2 子线程A运行 : 3 子线程B运行 : 3 子线程A运行 : 4 子线程B运行 : 4 子线程B运行 : 5 子线程A运行 : 5 子线程A运行 : 6 子线程A运行 : 7 子线程A运行 : 8 子线程B运行 : 6 子线程B运行 : 7 子线程B运行 : 8 子线程B运行 : 9 子线程A运行 : 9 Thread-1子线程运行结束! Thread-0子线程运行结束! main主线程运行结束!
4、yield()方法的使用
package com.thread; /** * Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。 * * yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。 * 但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。 * * 结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。 * * @author Administrator */ class ThreadYield1 extends Thread { public ThreadYield1(String name) { super(name); } @SuppressWarnings("static-access") public void run() { for (int i = 1; i <= 20; i++) { System.out.println("" + this.getName() + "-----" + i); // 当i为30时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行) if (i == 6) { System.out.println(this.getName()+"调用yield()方法开始"); this.yield(); System.out.println(this.getName()+"调用yield()方法结束"); } } } } class ThreadYield2 extends Thread { public ThreadYield2(String name) { super(name); } public void run() { for (int i = 1; i <= 20; i++) { System.out.println("" + this.getName() + "-----" + i); } } } public class Thread4{ public static void main(String[] args) { ThreadYield1 yt1 = new ThreadYield1("张三"); ThreadYield2 yt2 = new ThreadYield2("李四"); yt1.start(); yt2.start(); /** * setPriority(): 更改线程的优先级 * * MIN_PRIORITY = 1 * NORM_PRIORITY = 5 * MAX_PRIORITY = 10 */ yt2.setPriority(Thread.NORM_PRIORITY); yt1.setPriority(Thread.NORM_PRIORITY); } }
运行结果一:
张三-----1 李四-----1 张三-----2 李四-----2 张三-----3 李四-----3 张三-----4 李四-----4 张三-----5 张三-----6 张三调用yield()方法开始 张三调用yield()方法结束 张三-----7 张三-----8 张三-----9 张三-----10 张三-----11 张三-----12 张三-----13 张三-----14 张三-----15 张三-----16 张三-----17 张三-----18 张三-----19 张三-----20 李四-----5 李四-----6 李四-----7 李四-----8 李四-----9 李四-----10 李四-----11 李四-----12 李四-----13 李四-----14 李四-----15 李四-----16 李四-----17 李四-----18 李四-----19 李四-----20
运行结果二:
张三-----1 李四-----1 张三-----2 李四-----2 张三-----3 李四-----3 张三-----4 李四-----4 李四-----5 李四-----6 李四-----7 李四-----8 李四-----9 李四-----10 李四-----11 张三-----5 张三-----6 李四-----12 李四-----13 张三调用yield()方法开始 李四-----14 张三调用yield()方法结束 李四-----15 张三-----7 李四-----16 张三-----8 李四-----17 张三-----9 李四-----18 张三-----10 李四-----19 张三-----11 张三-----12 张三-----13 张三-----14 张三-----15 李四-----20 张三-----16 张三-----17 张三-----18 张三-----19 张三-----20
6、sleep()方法的使用
package com.thread; /** * sleep()和yield()的区别 * * sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行; * yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。 * sleep()方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的; * yield()方法使当前线程让出 CPU 占有权,但让出的时间是不可设定的。 * * 实际上,yield()方法对应了如下操作:先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把 CPU 的占有权交给此线程,否则,继续运行原来的线程。 * 所以yield()方法称为“退让”,它把运行机会让给了同等优先级的其他线程。 * 另外,sleep()方法允许较低优先级的线程获得运行机会,但 yield()方法执行时,当前线程仍处在可运行状态,所以,不可能让出较低优先级的线程些时获得 CPU 占有权。 * 在一个运行系统中,如果较高优先级的线程没有调用 sleep 方法,又没有受到 I\O 阻塞,那么,较低优先级线程只能等待所有较高优先级的线程运行结束,才有机会运行。 * * @author Administrator */ class ThreadSleep1 extends Thread { public ThreadSleep1(String name) { super(name); } @SuppressWarnings("static-access") public void run() { for (int i = 1; i <= 10; i++) { System.out.println("" + this.getName() + "-----" + i); // 当i为4时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行) if (i == 4) { try { System.out.println("休息五秒钟。。。。。。。。"); this.sleep(5000); System.out.println("我回来开始。。。。。。。。"); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class ThreadSleep2 extends Thread { public ThreadSleep2(String name) { super(name); } public void run() { for (int i = 1; i <= 10; i++) { System.out.println("" + this.getName() + "-----" + i); } } } public class Thread5{ public static void main(String[] args) { ThreadSleep1 yt1 = new ThreadSleep1("张三"); ThreadSleep2 yt2 = new ThreadSleep2("李四"); yt1.start(); yt2.start(); } }
运行结果:
张三-----1 李四-----1 张三-----2 张三-----3 张三-----4 李四-----2 休息五秒钟。。。。。。。。 李四-----3 李四-----4 李四-----5 李四-----6 李四-----7 李四-----8 李四-----9 李四-----10 我回来开始。。。。。。。。 张三-----5 张三-----6 张三-----7 张三-----8 张三-----9 张三-----10
参考:http://www.cnblogs.com/GarfieldEr007/p/5746362.html

浙公网安备 33010602011771号