1.        传统线程技术回顾

继承线程与实现Runnable的差异?为什么那么多人都采取第二种方式?

因为第二种方式更符合面向对象的思维方式。创建一个线程,线程要运行代码,而运行的代码都封装到一个独立的对象中去。一个叫线程,一个叫线程运行的代码,这是两个东西。两个东西一组合,就表现出了面向对象的思维。如果两个线程实现数据共享,必须用Runnable的方式。

查看Thread类的run()方法的源代码,可以看到其实这两种方式都是在调用Thread对象的run方法,如果Thread类的run方法没有被覆盖,并且为该Thread对象设置了一个Runnable对象,该run方法会调用Runnable对象的run方法。

问题如果在Thread子类覆盖的run方法中编写了运行代码,也为Thread子类对象传递了一个Runnable对象,那么,线程运行时的执行代码是子类的run方法的代码?还是Runnable对象的run方法的代码?子类的run方法。

示例代码

 

 1     new Thread(new Runnable() {
 2         public void run() {
 3             while (true) {
 4                 System.out.println("run:runnable");
 5             }
 6         }
 7     }) {
 8         public void run() {
 9             while (true) {
10                 try {
11                     Thread.sleep(1000);
12                 } catch (Exception e) {
13                 }
14                 System.out.println("run:thread");
15             }
16         }
17     }.start();

 

该线程会运行重写的Thread中的run方法,而不是Runnable中的run方法,因为在传统的Thread的run方法是:

1     public void run() {
2         if (target != null) {
3             target.run();
4         }   
5     }

 

如果想要运行Runnable中的run方法,必须在Thread中调用,但是此时我重写了Thread中的run方法,导致if (target != null) {  target.run();     }不存在,所以调用不了Runnable中的run方法。

注意:多线程的执行,会提高程序的运行效率吗?为什么会有多线程下载?

不会,有时候还会降低程序的运行效率。因为CPU只有一个,在CPU上下文切换的时候,可能还会耽误时间。

多线程下载:其实你的机器没有变快,而是你抢了服务器的带宽。如果你一个人下载,服务器给你提供的是20K的话,那么10个人的话,服务器提供的就是200K。这个时候你抢走200k,所以感觉变快了。

2.        传统定时器技术回顾(jdk1.5以前)Timer、TimerTask

Timer:一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。

scheduleAtFixedRate(TimerTask task, Date firstTime, long period):

安排指定的任务在指定的时间开始进行重复的固定速率执行。

schedule(TimerTask task, long delay, long period): 安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。

作业调度框架 Quartz(专门用来处理时间时间的工具)。你能够用它来为执行一个作业而创建简单的或复杂的调度。{ http://www.oschina.net/p/quartz}

问题:每天早晨3点来送报纸。

问题:每个星期周一到周五上班,周六道周日不上班。

示例代码:(间隔不同时间,执行不同事件)

 1 package com.chunjiangchao.thread;
 2 
 3 import java.util.Timer;
 4 import java.util.TimerTask;
 5 /**
 6  * 重复执行某项任务,但是时间间隔性不同是2,4这种状态
 7  * @author chunjiangchao
 8  *
 9  */
10 public class TimerDemo02 {
11     
12     private static long count = 1;
13     public static void main(String[] args) {
14         Timer timer =  new Timer();
15         timer.schedule(new Task(), 1000);
16         /*
17              测试打印结果如下:
18              执行任务,当前时间为:1460613231
19             执行任务,当前时间为:1460613235
20             执行任务,当前时间为:1460613237
21             执行任务,当前时间为:1460613241
22          */
23         
24     new Thread(new Runnable() {
25         public void run() {
26             while (true) {
27                 System.out.println("run:runnable");
28             }
29         }
30     }) {
31         public void run() {
32             while (true) {
33                 try {
34                     Thread.sleep(1000);
35                 } catch (Exception e) {
36                 }
37                 System.out.println("run:thread");
38             }
39         }
40     }.start();
41 
42         
43     }
44     
45     static class Task extends TimerTask{
46 
47         @Override
48         public void run() {
49             System.out.println("执行任务,当前时间为:"+System.currentTimeMillis()/1000);
50             new Timer().schedule(new Task(), 2000*(1+count%2));
51             count++;
52         }
53         
54     }
55 
56 }

 

3.        传统线程互斥技术

本道例题:关键在于说明:要想实现线程间的互斥,线程数量必须达到两个或者两个以上,同时,访问资源的时候要用同一把锁(这个是必须的)。如果两个线程都访问不同的同步代码块,而且它们的锁对象都不相同,那么这些线程就没有达到同步的目的。

示例代码:(访问同一个资源对象,但是锁对象不同,同样没有达到同步的目的)

 1 package com.chunjiangchao.thread;
 2 /**
 3  * 线程间同步与互斥
 4  * @author chunjiangchao
 5  * 因为print1方法与print3方法锁对象相同,所以在调用的时候,会产生互斥的现象,而print2的锁是当前正在执行对象print2方法的对象,
 6  * 与print1和print3同时执行,打印结果就不是期望的结果
 7  *
 8  */
 9 public class TraditionalThreadSynchronizedDemo {
10 
11     public static void main(String[] args) {
12         final MyPrint myPrint = new MyPrint();
13         //A
14         new Thread(new Runnable() {
15             
16             @Override
17             public void run() {
18                 myPrint.print1("chunjiangchao");
19             }
20         }).start();
21         //B
22 //        new Thread(new Runnable() {
23 //            
24 //            @Override
25 //            public void run() {
26 //                myPrint.print2("fengbianyun");
27 //            }
28 //        }).start();
29         //C
30         new Thread(new Runnable() {
31             
32             @Override
33             public void run() {
34                 myPrint.print3("liushaoyue");
35             }
36         }).start();
37     }
38     static class MyPrint{
39         public void print1(String str){
40             synchronized (MyPrint.class) {
41                 for(char c :str.toCharArray()){
42                     System.out.print(c);
43                     pSleep(200);
44                 }
45                 System.out.println("print1当前已经打印完毕");
46             }
47             
48         }
49         public synchronized void print2(String str){
50             for(char c :str.toCharArray()){
51                 System.out.print(c);
52                 pSleep(200);
53             }
54             System.out.println("print2当前已经打印完毕");
55         }
56         public synchronized static void print3(String str){
57             for(char c :str.toCharArray()){
58                 System.out.print(c);
59                 pSleep(200);
60             }
61             System.out.println("print3当前已经打印完毕");
62         }
63         private static void pSleep(long time){
64             try {
65                 Thread.sleep(time);
66             } catch (InterruptedException e) {
67                 e.printStackTrace();
68             }
69         }
70         
71     }
72 
73 }
View Code

相关文章: