赞
踩
现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。 “同时”执行是人的感觉,在线程之间实际上轮换执行。
Java中的线程
在Java中,“线程”指两件不同的事情:
1、java.lang.Thread类的一个实例;
2、线程的执行。
使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。一个Thread类实例只是一个对象,像Java中的任何其他对象一样,具有变量和方法,生死于堆上。Java中,每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行着。一个Java应用总是从main()方法开始运行,mian()方法运行在一个线程内,它被称为主线程。一旦创建一个新的线程,就产生一个新的调用栈。线程总体分两类:用户线程和守候线程。当所有用户线程执行完毕的时候,JVM自动关闭。但是守候线程却不独立于JVM,守候线程一般是由操作系统或者用户自己创建的。
定义线程
1、扩展java.lang.Thread类。
此类中有个run()方法,应该注意其用法:
public void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。Thread 的子类应该重写该方法。
2、实现java.lang.Runnable接口。
void run()
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。方法 run 的常规协定是,它可能执行任何所需的操作。
实例化线程
1、如果是扩展java.lang.Thread类的线程,则直接new即可。
2、如果是实现了java.lang.Runnable接口的类,则用Thread的构造方法:
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
启动线程
在线程的Thread对象上调用start()方法,而不是run()或者别的方法。在调用start()方法之前:线程处于新状态中,新状态指有一个Thread对象,但还没有一个真正的线程。
在调用start()方法之后:发生了一系列复杂的事情启动新的执行线程(具有新的调用栈);该线程从新状态转移到可运行状态;当该线程获得机会执行时,其目标run()方法将运行。
注意:对Java来说,run()方法没有任何特别之处。像main()方法一样,它只是新线程知道调用的方法名称(和签名)。因此,在Runnable上或者Thread上调用run方法是合法的。但并不启动新的线程。
例子
- /**
- * 实现Runnable接口的类
- *
- * @author TheDream 2012-12-3
- */
- public class DoSomething implements Runnable {
- private String name;
-
- public DoSomething(String name) {
- this.name = name;
- }
-
- public void run() {
- for (int i = 0; i < 5; i++) {
- for (long k = 0; k < 100000000; k++) ;
- System.out.println(name + ": " + i);
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- /**
- * 测试Runnable类实现的多线程程序
- *
- * @author TheDream 2012-12-3
- */
- public class TestRunnable {
- public static void main(String[] args) {
- DoSomething ds1 = new DoSomething("阿三");
- DoSomething ds2 = new DoSomething("李四");
-
- Thread t1 = new Thread(ds1);
- Thread t2 = new Thread(ds2);
-
- t1.start();
- t2.start();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
执行结果:
- 李四: 0
- 阿三: 0
- 李四: 1
- 阿三: 1
- 李四: 2
- 李四: 3
- 阿三: 2
- 李四: 4
- 阿三: 3
- 阿三: 4
-
- Process finished with exit code 0
扩展Thread类实现的多线程例子
- /**
- * 测试扩展Thread类实现的多线程程序
- *
- * @author TheDream 2012-12-3
- */
- public class TestThread extends Thread{
- public TestThread(String name) {
- super(name);
- }
-
- public void run() {
- for(int i = 0;i<5;i++){
- for(long k= 0; k <100000000;k++);
- System.out.println(this.getName()+" :"+i);
- }
- }
-
- public static void main(String[] args) {
- Thread t1 = new TestThread("阿三");
- Thread t2 = new TestThread("李四");
- t1.start();
- t2.start();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
执行结果:
- 阿三 :0
- 李四 :0
- 阿三 :1
- 李四 :1
- 阿三 :2
- 李四 :2
- 阿三 :3
- 阿三 :4
- 李四 :3
- 李四 :4
-
- Process finished with exit code 0
对于上面的多线程程序代码来说,输出的结果是不确定的。其中的一条语句for(long k= 0; k <100000000;k++);是用来模拟一个非常耗时的操作的。1、新状态:线程对象已经创建,还没有在其上调用start()方法。
2、可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。
3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
4、等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。
5、死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
阻止线程执行
对于线程的阻止,考虑一下三个方面,不考虑IO阻塞的情况:
睡眠;
等待;
因为需要一个对象的锁定而被阻塞。
1、睡眠
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。
线程睡眠的原因:线程执行太快,或者需要强制进入下一轮,因为Java规范不保证合理的轮换。
睡眠的实现:调用静态方法。
- try {
- Thread.sleep(123);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
睡眠的位置:为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠。- public void run() {
- for(int i = 0;i<5;i++){
- // 很耗时的操作,用来减慢线程的执行
- // for(long k= 0; k <100000000;k++);
- try {
- Thread.sleep(3);
- } catch (InterruptedException e) {
- e.printStackTrace(); .
- }
- System.out.println(this.getName()+" :"+i);
- }
- }
- 运行结果:
- 阿三 :0
- 李四 :0
- 阿三 :1
- 阿三 :2
- 阿三 :3
- 李四 :1
- 李四 :2
- 阿三 :4
- 李四 :3
- 李四 :4
- Process finished with exit code 0
这样,线程在每次执行过程中,总会睡眠3毫秒,睡眠了,其他的线程就有机会执行了。- /**
- * 一个计数器,计数到100,在每个数字之间暂停1秒,每隔10个数字输出一个字符串
- *
- * @author TheDream 2012-12-3
- */
- public class MyThread extends Thread {
- public void run() {
- for (int i = 0; i < 100; i++) {
- if ((i) % 10 == 0) {
- System.out.println("-------" + i);
- }
- System.out.print(i);
- try {
- Thread.sleep(1);
- System.out.print(" 线程睡眠1毫秒!\n");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- new MyThread().start();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
运行结果:
- -------0
- 0 线程睡眠1毫秒!
- 1 线程睡眠1毫秒!
- 2 线程睡眠1毫秒!
- 3 线程睡眠1毫秒!
- 4 线程睡眠1毫秒!
- 5 线程睡眠1毫秒!
- 6 线程睡眠1毫秒!
- 7 线程睡眠1毫秒!
- 8 线程睡眠1毫秒!
- 9 线程睡眠1毫秒!
- -------10
- 10 线程睡眠1毫秒!
- 11 线程睡眠1毫秒!
- 12 线程睡眠1毫秒!
- 13 线程睡眠1毫秒!
- 14 线程睡眠1毫秒!
- 15 线程睡眠1毫秒!
- 16 线程睡眠1毫秒!
- 17 线程睡眠1毫秒!
- 18 线程睡眠1毫秒!
- 19 线程睡眠1毫秒!
- -------20
- 20 线程睡眠1毫秒!
- 21 线程睡眠1毫秒!
- 22 线程睡眠1毫秒!
- 23 线程睡眠1毫秒!
- 24 线程睡眠1毫秒!
- 25 线程睡眠1毫秒!
- 26 线程睡眠1毫秒!
- 27 线程睡眠1毫秒!
- 28 线程睡眠1毫秒!
- 29 线程睡眠1毫秒!
- -------30
- 30 线程睡眠1毫秒!
- 31 线程睡眠1毫秒!
- 32 线程睡眠1毫秒!
- 33 线程睡眠1毫秒!
- 34 线程睡眠1毫秒!
- 35 线程睡眠1毫秒!
- 36 线程睡眠1毫秒!
- 37 线程睡眠1毫秒!
- 38 线程睡眠1毫秒!
- 39 线程睡眠1毫秒!
- -------40
- 40 线程睡眠1毫秒!
- 41 线程睡眠1毫秒!
- 42 线程睡眠1毫秒!
- 43 线程睡眠1毫秒!
- 44 线程睡眠1毫秒!
- 45 线程睡眠1毫秒!
- 46 线程睡眠1毫秒!
- 47 线程睡眠1毫秒!
- 48 线程睡眠1毫秒!
- 49 线程睡眠1毫秒!
- -------50
- 50 线程睡眠1毫秒!
- 51 线程睡眠1毫秒!
- 52 线程睡眠1毫秒!
- 53 线程睡眠1毫秒!
- 54 线程睡眠1毫秒!
- 55 线程睡眠1毫秒!
- 56 线程睡眠1毫秒!
- 57 线程睡眠1毫秒!
- 58 线程睡眠1毫秒!
- 59 线程睡眠1毫秒!
- -------60
- 60 线程睡眠1毫秒!
- 61 线程睡眠1毫秒!
- 62 线程睡眠1毫秒!
- 63 线程睡眠1毫秒!
- 64 线程睡眠1毫秒!
- 65 线程睡眠1毫秒!
- 66 线程睡眠1毫秒!
- 67 线程睡眠1毫秒!
- 68 线程睡眠1毫秒!
- 69 线程睡眠1毫秒!
- -------70
- 70 线程睡眠1毫秒!
- 71 线程睡眠1毫秒!
- 72 线程睡眠1毫秒!
- 73 线程睡眠1毫秒!
- 74 线程睡眠1毫秒!
- 75 线程睡眠1毫秒!
- 76 线程睡眠1毫秒!
- 77 线程睡眠1毫秒!
- 78 线程睡眠1毫秒!
- 79 线程睡眠1毫秒!
- -------80
- 80 线程睡眠1毫秒!
- 81 线程睡眠1毫秒!
- 82 线程睡眠1毫秒!
- 83 线程睡眠1毫秒!
- 84 线程睡眠1毫秒!
- 85 线程睡眠1毫秒!
- 86 线程睡眠1毫秒!
- 87 线程睡眠1毫秒!
- 88 线程睡眠1毫秒!
- 89 线程睡眠1毫秒!
- -------90
- 90 线程睡眠1毫秒!
- 91 线程睡眠1毫秒!
- 92 线程睡眠1毫秒!
- 93 线程睡眠1毫秒!
- 94 线程睡眠1毫秒!
- 95 线程睡眠1毫秒!
- 96 线程睡眠1毫秒!
- 97 线程睡眠1毫秒!
- 98 线程睡眠1毫秒!
- 99 线程睡眠1毫秒!
- Process finished with exit code 0
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
2、线程的优先级和线程让步yield()- Thread t = new MyThread();
- t.setPriority(8);
- t.start();
线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。然而,1~10之间的值是没有保证的。一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。- Thread t = new MyThread();
- t.start();
- t.join();
另外,join()方法还有带超时限制的重载版本。 例如t.join(5000);则让线程等待5000毫秒,如果超过这个时间,则停止等待,变为可运行状态。同步问题提出
线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。
- public class Foo {
- private int x = 100;
- public int getX() {
- return x;
- }
- public int fix(int y) {
- x = x - y;
- return x;
- }
- }
- public class MyRunnable implements Runnable {
- private Foo foo = new Foo();
- public static void main(String[] args) {
- MyRunnable r = new MyRunnable();
- Thread ta = new Thread(r, "Thread-A");
- Thread tb = new Thread(r, "Thread-B");
- ta.start();
- tb.start();
- }
- public void run() {
- for (int i = 0; i < 3; i++) {
- this.fix(30);
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + " : 当前foo对象的x值= " + foo.getX());
- }
- }
- public int fix(int y) {
- return foo.fix(y);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 运行结果:
- Thread-A : 当前foo对象的x值= 40
- Thread-B : 当前foo对象的x值= 40
- Thread-B : 当前foo对象的x值= -20
- Thread-A : 当前foo对象的x值= -50
- Thread-A : 当前foo对象的x值= -80
- Thread-B : 当前foo对象的x值= -80
- Process finished with exit code 0
从结果发现,这样的输出值明显是不合理的。原因是两个线程不加控制的访问Foo对象并修改其数据所致。- public int fix(int y) {
- synchronized (this) {
- x = x - y;
- }
- return x;
- }
当然,同步方法也可以改写为非同步方法,但功能完全一样的,例如:
- public synchronized int getX() {
- return x++;
- }
与
- public int getX() {
- synchronized (this) {
- return x;
- }
- }
效果是完全一样的。
- public static synchronized int setName(String name){
- Xxx.name = name;
- }
等价于
- public static int setName(String name){
- synchronized(Xxx.class){
- Xxx.name = name;
- }
- }
如果线程不能不能获得锁会怎么样
对于非静态字段中可更改的数据,通常使用非静态方法访问。
对于静态字段中可更改的数据,通常使用静态方法访问。
如果需要在非静态方法中使用静态字段,或者在静态字段中调用非静态方法,问题将变得非常复杂。
线程安全类
当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”。即使是线程安全类,也应该特别小心,因为操作的线程是间仍然不一定安全。举个形象的例子,比如一个集合是线程安全的,有两个线程在操作同一个集合对象,当第一个线程查询集合非空后,删除集合中所有元素的时候。第二个线程也来执行与第一个线程相同的操作,也许在第一个线程查询后,第二个线程也查询出集合非空,但是当第一个执行清除后,第二个再执行删除显然是不对的,因为此时集合已经为空了。
看个代码:
- public class NameList {
- private List nameList = Collections.synchronizedList(new LinkedList());
- public void add(String name) {
- nameList.add(name);
- }
- public String removeFirst() {
- if (nameList.size() > 0) {
- return (String) nameList.remove(0);
- } else {
- return null;
- }
- }
- }
- public class Test {
- public static void main(String[] args) {
- final NameList nl = new NameList();
- nl.add("aaa");
- class NameDropper extends Thread{
- public void run(){
- String name = nl.removeFirst();
- System.out.println(name);
- }
- }
- Thread t1 = new NameDropper();
- Thread t2 = new NameDropper();
- t1.start();
- t2.start();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
虽然集合对象
private List nameList = Collections.synchronizedList(new LinkedList());
是同步的,但是程序还不是线程安全的。- public class NameList {
- private List nameList = Collections.synchronizedList(new LinkedList());
- public synchronized void add(String name) {
- nameList.add(name);
- }
- public synchronized String removeFirst() {
- if (nameList.size() > 0) {
- return (String) nameList.remove(0);
- } else {
- return null;
- }
- }
- }
这样,当一个线程访问其中一个同步方法时,其他线程只有等待。
- public class DeadlockRisk {
- private static class Resource {
- public int value;
- }
- private Resource resourceA = new Resource();
- private Resource resourceB = new Resource();
- public int read() {
- synchronized (resourceA) {
- synchronized (resourceB) {
- return resourceB.value + resourceA.value;
- }
- }
- }
- public void write(int a, int b) {
- synchronized (resourceB) {
- synchronized (resourceA) {
- resourceA.value = a;
- resourceB.value = b;
- }
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
假设read()方法由一个线程启动,write()方法由另外一个线程启动。读线程将拥有resourceA锁,写线程将拥有resourceB锁,两者都坚持等待的话就出现死锁。
- /**
- * 计算输出其他线程锁计算的数据
- *
- * @author TheDream 2012-12-3
- */
- public class ThreadA {
- public static void main(String[] args) {
- ThreadB b = new ThreadB();
- //启动计算线程
- b.start();
- //线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者
- synchronized (b) {
- try {
- System.out.println("等待对象b完成计算。。。");
- //当前线程A等待
- b.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("b对象计算的总和是:" + b.total);
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- /**
- * 计算1+2+3 ... +100的和
- *
- * @author TheDream 2012-12-3
- */
- public class ThreadB extends Thread {
- int total;
- public void run() {
- synchronized (this) {
- for (int i = 0; i < 101; i++) {
- total += i;
- }
- //(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒
- notify();
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 等待对象b完成计算。。。
- b对象计算的总和是:5050
- Process finished with exit code 0
千万注意:- /**
- * 计算线程
- *
- * @author TheDream 2012-12-3
- */
- public class Calculator extends Thread {
- int total;
- public void run() {
- synchronized (this) {
- for (int i = 0; i < 101; i++) {
- total += i;
- }
- }
- //通知所有在此对象上等待的线程
- notifyAll();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- /**
- * 获取计算结果并输出
- *
- * @author TheDream 2012-12-3
- */
- public class ReaderResult extends Thread {
- Calculator c;
- public ReaderResult(Calculator c) {
- this.c = c;
- }
- public void run() {
- synchronized (c) {
- try {
- System.out.println(Thread.currentThread() + "等待计算结果。。。");
- c.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread() + "计算结果为:" + c.total);
- }
- }
- public static void main(String[] args) {
- Calculator calculator = new Calculator();
- //启动三个线程,分别获取计算结果
- new ReaderResult(calculator).start();
- new ReaderResult(calculator).start();
- new ReaderResult(calculator).start();
- //启动计算线程
- calculator.start();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 运行结果:
- Thread[Thread-1,5,main]等待计算结果。。。
- Thread[Thread-2,5,main]等待计算结果。。。
- Thread[Thread-3,5,main]等待计算结果。。。
- Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread not owner
- at java.lang.Object.notifyAll(Native Method)
- at threadtest.Calculator.run(Calculator.java:18)
- Thread[Thread-1,5,main]计算结果为:5050
- Thread[Thread-2,5,main]计算结果为:5050
- Thread[Thread-3,5,main]计算结果为:5050
- Process finished with exit code 0
运行结果表明,程序中有异常,并且多次运行结果可能有多种输出结果。这就是说明,这个多线程的交互程序还存在问题。究竟是出了什么问题,需要深入的分析和思考,下面将做具体分析。- /**
- * Java线程:线程的调度-休眠
- *
- * @author TheDream 2012年12月3日
- */
- public class Test {
- public static void main(String[] args) {
- Thread t1 = new MyThread1();
- Thread t2 = new Thread(new MyRunnable());
- t1.start();
- t2.start();
- }
- }
- class MyThread1 extends Thread {
- public void run() {
- for (int i = 0; i < 3; i++) {
- System.out.println("线程1第" + i + "次执行!");
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class MyRunnable implements Runnable {
- public void run() {
- for (int i = 0; i < 3; i++) {
- System.out.println("线程2第" + i + "次执行!");
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
执行结果:
- 线程2第0次执行!
- 线程1第0次执行!
- 线程1第1次执行!
- 线程2第1次执行!
- 线程1第2次执行!
- 线程2第2次执行!
- Process finished with exit code 0
从上面的结果输出可以看出,无法精准保证线程执行次序。
- /**
- * Java线程:线程的调度-优先级
- *
- * @author TheDream 2012年12月3日
- */
- public class Test {
- public static void main(String[] args) {
- Thread t1 = new MyThread1();
- Thread t2 = new Thread(new MyRunnable());
- t1.setPriority(10);
- t2.setPriority(1);
-
-
- t2.start();
- t1.start();
- }
- }
- class MyThread1 extends Thread {
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println("线程1第" + i + "次执行!");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class MyRunnable implements Runnable {
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println("线程2第" + i + "次执行!");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
执行结果:
- 线程1第0次执行!
- 线程2第0次执行!
- 线程2第1次执行!
- 线程1第1次执行!
- 线程2第2次执行!
- 线程1第2次执行!
- 线程1第3次执行!
- 线程2第3次执行!
- 线程2第4次执行!
- 线程1第4次执行!
- 线程1第5次执行!
- 线程2第5次执行!
- 线程1第6次执行!
- 线程2第6次执行!
- 线程1第7次执行!
- 线程2第7次执行!
- 线程1第8次执行!
- 线程2第8次执行!
- 线程1第9次执行!
- 线程2第9次执行!
- Process finished with exit code 0
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
线程的调度-让步
- /**
- * Java线程:线程的调度-让步
- *
- * @author TheDream 2012年12月3日
- */
- public class Test {
- public static void main(String[] args) {
- Thread t1 = new MyThread1();
- Thread t2 = new Thread(new MyRunnable());
-
-
- t2.start();
- t1.start();
- }
- }
-
-
- class MyThread1 extends Thread {
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println("线程1第" + i + "次执行!");
- }
- }
- }
- class MyRunnable implements Runnable {
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println("线程2第" + i + "次执行!");
- Thread.yield();
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 线程2第0次执行!
- 线程2第1次执行!
- 线程2第2次执行!
- 线程2第3次执行!
- 线程1第0次执行!
- 线程1第1次执行!
- 线程1第2次执行!
- 线程1第3次执行!
- 线程1第4次执行!
- 线程1第5次执行!
- 线程1第6次执行!
- 线程1第7次执行!
- 线程1第8次执行!
- 线程1第9次执行!
- 线程2第4次执行!
- 线程2第5次执行!
- 线程2第6次执行!
- 线程2第7次执行!
- 线程2第8次执行!
- 线程2第9次执行!
- Process finished with exit code 0
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
线程的调度-合并
- /**
- * Java线程:线程的调度-合并
- *
- * @author TheDream 2012年12月3日
- */
- public class Test {
- public static void main(String[] args) {
- Thread t1 = new MyThread1();
- t1.start();
- for (int i = 0; i < 20; i++) {
- System.out.println("主线程第" + i + "次执行!");
- if (i > 2) try {
- //t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续。
- t1.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- lass MyThread1 extends Thread {
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println("线程1第" + i + "次执行!");
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
执行结果:
- 主线程第0次执行!
- 主线程第1次执行!
- 主线程第2次执行!
- 线程1第0次执行!
- 主线程第3次执行!
- 线程1第1次执行!
- 线程1第2次执行!
- 线程1第3次执行!
- 线程1第4次执行!
- 线程1第5次执行!
- 线程1第6次执行!
- 线程1第7次执行!
- 线程1第8次执行!
- 线程1第9次执行!
- 主线程第4次执行!
- 主线程第5次执行!
- 主线程第6次执行!
- 主线程第7次执行!
- 主线程第8次执行!
- 主线程第9次执行!
- 主线程第10次执行!
- 主线程第11次执行!
- 主线程第12次执行!
- 主线程第13次执行!
- 主线程第14次执行!
- 主线程第15次执行!
- 主线程第16次执行!
- 主线程第17次执行!
- 主线程第18次执行!
- 主线程第19次执行!
- Process finished with exit code 0
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
线程的调度-守护线程
- /**
- * Java线程:线程的调度-守护线程
- *
- * @author TheDream 2012年12月3日
- */
- public class Test {
- public static void main(String[] args) {
- Thread t1 = new MyCommon();
- Thread t2 = new Thread(new MyDaemon());
- t2.setDaemon(true); //设置为守护线程
-
-
- t2.start();
- t1.start();
- }
- }
- class MyCommon extends Thread {
- public void run() {
- for (int i = 0; i < 5; i++) {
- System.out.println("线程1第" + i + "次执行!");
- try {
- Thread.sleep(7);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class MyDaemon implements Runnable {
- public void run() {
- for (long i = 0; i < 9999999L; i++) {
- System.out.println("后台线程第" + i + "次执行!");
- try {
- Thread.sleep(7);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 后台线程第0次执行!
- 线程1第0次执行!
- 线程1第1次执行!
- 后台线程第1次执行!
- 后台线程第2次执行!
- 线程1第2次执行!
- 线程1第3次执行!
- 后台线程第3次执行!
- 线程1第4次执行!
- 后台线程第4次执行!
- 后台线程第5次执行!
- 后台线程第6次执行!
- 后台线程第7次执行!
- Process finished with exit code 0
从上面的执行结果可以看出:Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。