Java多线程及JDK5线程工具类总结

内容摘抄来自:传智播客 张孝祥 老师的《Java高新技术》视频,   并加入了个人总结和理解。

虽然我没有参加过任何培训班,但我很大一部分知识都来自于传智播客的网络分享视频。

十分真挚的感谢张老师的公开视频。

1.传统线程技术的回顾

 1 import org.junit.Test;
 2 /**
 3  * 传统线程回顾
 4  * 多线程不一定会提高运行效率,和CPU设计和架构有关。
 5  * 多线程下载是抢了服务器的资源,并不是自身的机器加快。
 6  * @author LiTaiQing
 7  */
 8 public class TraditionThread {
 9     /**
10      * 两种传统线程的创建方式
11      */
12     @Test
13     public void test1(){
14         //方式一
15         Thread thread = new Thread(){
16             /**
17              * 从Thread.class源代码中发现,run方法在默认情况下是执行默认target.run();
18              *  @Override
19                 public void run() {
20                     if (target != null) {
21                         target.run();
22                     }
23                 }
24
25                 private Runnable target;
26              */
27             @Override
28             public void run() {
29                 while(true){
30                     System.out.println(Thread.currentThread().getName());
31                     //不要使用this,因为在Runnable创建线程的方式中this是无效的
32                     //System.out.println(this.getName());
33                 }
34             }
35         };
36         thread.start();
37         /**
38          * 方式二
39          * 使用Runnable更好,更加符合面向对象程序设计的思想,程序结构的耦合性更低,将任务和宿主分离
40          */
41         Thread thread2 = new Thread(new Runnable(){
42             @Override
43             public void run() {
44                 while(true){
45                     System.out.println(Thread.currentThread().getName());
46                     //报错
47                     //System.out.println(this.getName());
48                 }
49             }
50         });
51         thread2.start();
52         //-------------------------------------
53         /**
54          * 考虑回运行哪一块代码?
55          */
56         new Thread(new Runnable(){
57             @Override
58             public void run() {
59                 while(true){
60                     try {
61                         Thread.sleep(500);
62                     } catch (InterruptedException e) {
63                         e.printStackTrace();
64                     }
65                     System.out.println("Runable:"+Thread.currentThread().getName());
66                 }
67             }
68         }){
69             /**
70              *     会运行此代码块,子类覆盖了父类的方法 ,那么就先运行子类,否则就去找父类
71              */
72             @Override
73             public void run() {
74                 while(true){
75                     try {
76                         Thread.sleep(500);
77                     } catch (InterruptedException e) {
78                         e.printStackTrace();
79                     }
80                     System.out.println("Run:"+Thread.currentThread().getName());
81                 }
82             }
83         }.start();
84     }
85 }

2.传统定时器技术回顾   -   Timer类   TimerTask

java.util 
类 Timer

java.lang.Object  java.util.Timer
方法摘要
void cancel() 
          终止此计时器,丢弃所有当前已安排的任务。
 int purge() 
          从此计时器的任务队列中移除所有已取消的任务。
void schedule(TimerTask task, Date time) 
          安排在指定的时间执行指定的任务。
void schedule(TimerTask task, Date firstTime, long period) 
          安排指定的任务在指定的时间开始进行重复的固定延迟执行
void schedule(TimerTask task, long delay) 
          安排在指定延迟后执行指定的任务。
void schedule(TimerTask task, long delay, long period) 
          安排指定的任务从指定的延迟后开始进行重复的固定延迟执行
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 
          安排指定的任务在指定的时间开始进行重复的固定速率执行
void scheduleAtFixedRate(TimerTask task, long delay, long period) 
          安排指定的任务在指定的延迟后开始进行重复的固定速率执行
 1 import java.util.Date;
 2 import java.util.Timer;
 3 import java.util.TimerTask;
 4 import org.junit.Test;
 5 /**
 6  * 传统定时器
 7  * 工具 quartz 可以完成在周几执行任务的需求
 8  * @author LiTaiQing
 9  */
10 public class TraditionalTimerTest {
11     /**
12      * 传统定时器的使用实例
13      */
14     @Test
15     public void test1(){
16         /*
17          * schedule 调度
18          * Timer是定时器
19          * TimerTask是定时器的任务
20          */
21         new Timer().schedule(new TimerTask(){
22             @Override
23             public void run() {
24                 System.out.println("bombing!");
25             }
26         }, 10000,3000);//第一次执行是10秒之后,以后每隔3秒执行一次
27         printSeconds();
28     }
29
30     /**
31      * 实现刚开始2秒执行,之后4秒执行一次
32      *         代码思想从每次2秒执行一次改到目标结果
33      */
34     //通过一个标记,判断当前任务应该多少秒后执行
35     private static int count = 0;
36     @Test
37     public void test2(){
38         /**
39          * 内部类内部不能出现静态变量。
40          */
41         class MyTimerTask extends TimerTask{
42             @Override
43             public void run() {
44                 count = (count + 1)%2;
45                 System.out.println("bombing!");
46                 new Timer().schedule(
47                     /*new TimerTask(){
48                         @Override
49                         public void run() {
50                             System.out.println("bombing!");
51                         }
52                     }*/
53                 new MyTimerTask(), 2000+2000*count);
54             }
55         }
56         new Timer().schedule(new MyTimerTask(),2000);
57         printSeconds();
58     }
59
60     /**
61      * “实现任务刚开始2秒执行,之后4秒执行一次”的另一种方法
62      */
63     @Test
64     public void test3(){
65         new Timer().schedule(new MyTimerTask2(), 2000);
66         printSeconds();
67     }
68     class MyTimerTask1 extends TimerTask{
69         @Override
70         public void run() {
71             System.out.println("bombing!");
72             new Timer().schedule(new MyTimerTask2(), 2000);
73         }
74     }
75     class MyTimerTask2 extends TimerTask{
76         @Override
77         public void run() {
78             System.out.println("bombing!");
79             new Timer().schedule(new MyTimerTask1(), 4000);
80         }
81     }
82
83     private void printSeconds(){
84         while(true){
85             System.out.println(new Date().getSeconds());
86             try {
87                 Thread.sleep(1000);
88             } catch (InterruptedException e) {
89                 e.printStackTrace();
90             }
91         }
92     }
93 }

3.传统线程互斥技术

线程安全问题可以用银行转账来解释

 1 /**
 2  * 传统的线程互斥技术
 3  * @author LiTaiQing
 4  */
 5 public class TraditionalThreadSynchronized {
 6
 7     public static void main(String[] args){
 8         new TraditionalThreadSynchronized().init();
 9     }
10
11     private void init(){
12         /**
13          * 内部类访问局部变量,局部变量要加final
14          *         若此代码放在main中会报错,因为静态代码块不能访问内部类
15          */
16         final Outputer outputer = new Outputer();
17         new Thread(new Runnable(){
18             @Override
19             public void run() {
20                 while(true){
21                     try {
22                         Thread.sleep(1000);
23                     } catch (InterruptedException e) {
24                         e.printStackTrace();
25                     }
26                     outputer.output("zhangxiaoxiang");
27                 }
28             }
29         }).start();
30         new Thread(new Runnable(){
31             @Override
32             public void run() {
33                 while(true){
34                     try {
35                         Thread.sleep(1000);
36                     } catch (InterruptedException e) {
37                         e.printStackTrace();
38                     }
39                     outputer.output("lihuoming");
40                 }
41             }
42         }).start();
43     }
44
45     static class Outputer{
46         public void output(String name){
47             int len = name.length();
48             /*
49              * 锁用任意一个对象都行,但只有同一个对象才具有互斥性
50              * 1.每个类的字节码文件只有一份,可以用来做互斥锁
51              * 2.用this也行
52              * 此处也可以在方法上架synchroized,
53              * 但从多线程效率角度来看,合理细化同步块粒度能提高执行效率,
54              * 所以此处在内部代码中加synchroized比较好
55              */
56             synchronized(Outputer.class){
57                 for(int i = 0; i < len ; i++){
58                     System.out.print(name.charAt(i));
59                 }
60                 System.out.println();
61             }
62         }
63         /**
64          * output2方法不会同步,因为方法上加synchronized相当于加this锁
65          * 但又是静态方法,所以this会失效,会出现问题。
66          * @param name
67          */
68         public static synchronized void output2(String name){
69             int len = name.length();
70             synchronized(Outputer.class){
71                 for(int i = 0; i < len ; i++){
72                     System.out.print(name.charAt(i));
73                 }
74                 System.out.println();
75             }
76         }
77     }
78 }

4.传统线程同步通信技

 1 /**
 2  * 传统线程同步通信技术
 3  *
 4  * *******************************************
 5  * 经验:
 6  *       要用到共同数据(包括共同锁)或共同算法的若干个方法应该
 7  * 归在用一个类身上,这种设计正好体现了高内聚和程序的健壮性。
 8  *
 9  * *******************************************
10  *
11  * @author LiTaiQing
12  */
13 public class TraditionalThreadCommunication {
14
15     /**************************************************
16      * 调试小技巧
17      * 如果由于Console的输出太多而造成面板显示的数据不完整
18      * 可设置运行前参数设置
19      * 右键->Run As->Run Configuractions->Common->File
20      * 选择保存的路径即可
21      *
22      **************************************************
23      */
24
25
26     /**
27      * 面试题
28      * ·子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,
29      * ·接着再回到主线程又循环100,如此循环50次,请写出程序
30      */
31     public static void main(String[] args){
32
33         final Business business = new Business();
34         new Thread(new Runnable(){
35             @Override
36             public void run() {
37                 for(int i = 1; i <= 50; i++){
38                     business.sub(i);
39                 }
40             }
41         }).start();
42         for(int i = 1; i <= 50; i++){
43             business.main(i);
44         }
45     }
46
47 }
48
49 class Business{
50     private boolean bShouldSub = true;
51     public synchronized void sub(int i){
52         /**
53          * 此处将if改为while,增强代码健壮性。
54          * 防止伪唤醒!
55          */
56         while(!bShouldSub){
57             try {
58                 this.wait();
59             } catch (InterruptedException e) {
60                 e.printStackTrace();
61             }
62         }
63         for(int j = 1; j <= 10; j++){
64             System.out.println("sub thread sequece of " + j + ",loop of " +i);
65         }
66         bShouldSub = false;
67         this.notify();
68     }
69     public synchronized void main(int i){
70         while(bShouldSub){
71             try {
72                 this.wait();
73             } catch (InterruptedException e) {
74                 e.printStackTrace();
75             }
76         }
77         for(int j = 1; j <= 100; j++){
78             System.out.println("main thread sequece of " + j + ",loop of " +i);
79         }
80         bShouldSub = true;
81         this.notify();
82     }
83 }

5.线程范围内共享变量的概念与作用

 1 import java.util.HashMap;
 2 import java.util.Map;
 3 import java.util.Random;
 4
 5 /*******************************
 6  * 模拟ThrealLocal的实现
 7  * 用处:
 8  *  用在数据库操作中俄beginTransaction -> commit
 9  *  在Hibernate中也是使用它来保证在多线程下Session自己不冲突。
10  *     OpenSessionInView模式
11  *        spring的OpenSessionInView也是使用ThreadLocal来实现, OpenSessionInViewFilter过滤器
12  *        当请求到底是打开一个session,请求结束时关闭。
13  *        缺陷就是如果客户端的网速慢,会导致数据库的链接一直被占用。
14  *    扩展:OpenSessionInView模式用AOP替代
15  * *****************************
16  * @author LiTaiQing
17  */
18 public class ThreadScopeShareData {
19     private static Map<Thread,Integer> threadData = new HashMap<Thread,Integer>();
20     public static void main(String[] args){
21         for(int i = 0; i < 10 ; i++){
22             new Thread(new Runnable(){
23                 @Override
24                 public void run() {
25                     int data = new Random().nextInt();
26                     System.out.println(Thread.currentThread().getName() + " get put data :" + data);
27                     threadData.put(Thread.currentThread(), data);
28                     new A().get();
29                     new B().get();
30                 }
31             }).start();
32         }
33     }
34     static class A{
35         public void get(){
36             int data = threadData.get(Thread.currentThread());
37             System.out.println("A from" + Thread.currentThread().getName() + " get put data :" + data);
38         }
39     }
40     static class B{
41         public void get(){
42             int data = threadData.get(Thread.currentThread());
43             System.out.println("B from" + Thread.currentThread().getName() + " get put data :" + data);
44         }
45     }
时间: 2024-10-11 07:35:33

Java多线程及JDK5线程工具类总结的相关文章

廖雪峰Java11多线程编程-4线程工具类-1ThreadLocal

class User{ String name; int level; public User(String name, int level){ this.name = name; this.level = level; } } class UserContext implements AutoCloseable{ static final ThreadLocal<User> context = new ThreadLocal<>(); public static User get

java多线程并发去调用一个类的静态方法安全性探讨

java多线程并发去调用一个类的静态方法安全性探讨 转自:http://blog.csdn.net/weibin_6388/article/details/50750035 这篇文章主要讲多线程对静态方法访问的数据安全性 总结如下: 1,java在执行静态方法时,会在内存中拷贝一份,如果静态方法所在的类里面没有静态的变量,那么线程访问就是安全的,比如在javaee中服务器必然会多线程的处理请求此时如果设计全局需要调用的静态方法,可用此种设计. 2,java在执行静态方法时,如果使用静态变量,同时

java中IO写文件工具类

下面是一些根据常用java类进行组装的对文件进行操作的类,平时,我更喜欢使用Jodd.io中提供的一些对文件的操作类,里面的方法写的简单易懂. 其中jodd中提供的JavaUtil类中提供的方法足够我们使用,里面的方法写的非常简练,例如append,read等方法,封装更好,更符合面向对象, 这里面我写的一些方法可多都是模仿jodd,从里面进行抽取出来的. /** * 获取路径文件夹下的所有文件 * @param path * @return */ public static File[] ge

Java多线程之后台线程不执行finally

后台线程不执行finally package wzh.daemon; import java.util.concurrent.TimeUnit; class ADaemon implements Runnable { @Override public void run() { try { System.out.println("Starting ADaemon"); TimeUnit.SECONDS.sleep(1); } catch (Exception e) { System.ou

Java多线程之后台线程

将线程设置成后台线程Daemons 主线程结果后,后台线程将自动结果. package wzh.test; import java.util.concurrent.TimeUnit; class SimpleDaemons implements Runnable{ @Override public void run() { try { while (true) { TimeUnit.MILLISECONDS.sleep(100); System.out.println(Thread.curren

Java随机取字符串的工具类

原文:Java随机取字符串的工具类 源代码下载地址:http://www.zuidaima.com/share/1550463479532544.htm Java 随机取字符串的工具类 可以全部是数字,字符,也可以字符和数字组合的工具类,希望能给大家带来帮助 package com.zuidaima.test; import java.util.Random; public class RandomUtils { public static final String ALLCHAR = "012

java实现发邮件的工具类,方便 好用(需要架包的Send Email To me)

原文:java实现发邮件的工具类,方便 好用(需要架包的Send Email To me) 源代码下载地址:http://www.zuidaima.com/share/1550463394794496.htm package com.zuidaima.util; import java.util.Properties; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.Multipart; impor

java HTML字符串正则表达式使用工具类

原文:java HTML字符串正则表达式使用工具类 代码下载地址:http://www.zuidaima.com/share/1550463453416448.htm HTML相关的正则表达式工具类 包括过滤HTML标记,转换HTML标记,替换特定HTML标记 package com.zuidaima.common.util; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * <p> * Title: H

Java 基于log4j的日志工具类

Java 基于log4j的日志工具类 对log4j日志类进行了简单封装,使用该封装类的优势在于以下两点: 1.不必在每个类中去创建对象,直接类名 + 方法即可 2.可以很方便的打印出堆栈信息 package com.tradeplatform.receiveorder.util; import java.io.PrintWriter; import java.io.StringWriter; import org.apache.log4j.Logger; /** * @Description 日