线程的理解

本文通过实例演示了Java中线程并发的实现方法,包括线程类的定义、启动及执行顺序的随机性,强调了代码组织的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

在开始这个话题之前,我们先聊一下线程。线程的目的就是为了让一些程序片段能够“同时”进行,至少是视觉上。因为实际上,这些程序片段是“交替”执行的。如图1

 

在途中,线程A和线程B轮流交替地占有CPU的处理时间。也许有人说,CPU总的计算量并没有降低啊,确实如此,还可以切换线程,还增加了一点点的计算量。如果现在有一个很长很复杂很费时的计算任务,和一个精彩电影的播放任务,那我们当然愿意选择让这两个不太相干的任务同时并发执行。由此可见线程的目的是用一些调度算法,使电脑用户不会“等待”的不耐烦。因为绝大多数的用户都希望计算机体贴周到,富有人性化,提供更好的服务。事实上,我们在计算机上做的很多革新,就是为了如此。

       Java是支持线程的,不像C++,还需要操作系统的配合才行,当然java最终还是要用到操作系统底层的支持,才可以拥有多线程编程的能力,呵呵。Java实现线程非常简单。一个是继承Thread,一个是实现Runnable接口。我突然想起我毕业时面试时经常被问这样的问题,那时只不过是机械式的回答,里面有许多的道理倒没有现在认识深刻。我们需要并发的代码写在run方法里面就OK了,呵呵。至于java底层是如何压栈入栈,保护程序执行现场的,如何恢复现场的,我们就不必深究了,因为我们不是API级的程序员,我们需要的是学习别人的成果,迅速copy,快速开发,不然怎么超英赶美啊?我们的目的是为了图2中的“顺序执行”变成图1中的“并发执行”。其中图1中的“时间片”的划分是随机的。

Java的线程执行,也是非常简单的,new 一个线程,然后startOK了。

关于Thread这个类,有时候容易混淆。打个比方说,使用这个类可以类比成英语里面的语法“Somebody do Something”。举个例子:

SomeBody类:

  

Java代码 复制代码
  1. package wjj2;   
  2.   
  3. public class SomeBody {   
  4.        
  5.     private String name;   
  6.     public SomeBody(String name)   
  7.     {   
  8.         this.name=name;   
  9.     }   
  10.        
  11.     public void someBodyDo()   
  12.     {   
  13.         System.out.println(this.name+"早上7:45起床");   
  14.         //随机生成停顿时间,为了模拟较长的代码执行时间,以下都是类似   
  15.         try {   
  16.             int a=(int) ((long)1000* Math.random());   
  17.             System.out.println(a);   
  18.             Thread.sleep(a);   
  19.         } catch (InterruptedException e) {   
  20.             // TODO Auto-generated catch block   
  21.             e.printStackTrace();   
  22.         }   
  23.            
  24.         System.out.println(this.name+"7:50大便");   
  25.            
  26.         try {   
  27.             int a=(int) ((long)1000* Math.random());   
  28.             System.out.println(a);   
  29.             Thread.sleep(a);   
  30.         } catch (InterruptedException e) {   
  31.             // TODO Auto-generated catch block   
  32.             e.printStackTrace();   
  33.         }   
  34.            
  35.         System.out.println(this.name+"8:00刷牙,顺带刷刷舌苔");   
  36.         try {   
  37.             int a=(int) ((long)1000* Math.random());   
  38.             System.out.println(a);   
  39.             Thread.sleep(a);   
  40.         } catch (InterruptedException e) {   
  41.             // TODO Auto-generated catch block   
  42.             e.printStackTrace();   
  43.         }   
  44.            
  45.         System.out.println(this.name+"8:05洗脸");   
  46.            
  47.         try {   
  48.             int a=(int) ((long)1000* Math.random());   
  49.             System.out.println(a);   
  50.             Thread.sleep(a);   
  51.         } catch (InterruptedException e) {   
  52.             // TODO Auto-generated catch block   
  53.             e.printStackTrace();   
  54.         }   
  55.         System.out.println(this.name+"8:10搽雪花膏");   
  56.            
  57.         try {   
  58.             int a=(int) ((long)1000* Math.random());   
  59.             System.out.println(a);   
  60.             Thread.sleep(a);   
  61.         } catch (InterruptedException e) {   
  62.             // TODO Auto-generated catch block   
  63.             e.printStackTrace();   
  64.         }   
  65.         System.out.println(this.name+"8:20到车站");   
  66.            
  67.         try {   
  68.             int a=(int) ((long)1000* Math.random());   
  69.             System.out.println(a);   
  70.             Thread.sleep(a);   
  71.         } catch (InterruptedException e) {   
  72.             // TODO Auto-generated catch block   
  73.             e.printStackTrace();   
  74.         }   
  75.         System.out.println(this.name+"8:30搭上车");   
  76.         try {   
  77.             int a=(int) ((long)1000* Math.random());   
  78.             System.out.println(a);   
  79.             Thread.sleep(a);   
  80.         } catch (InterruptedException e) {   
  81.             // TODO Auto-generated catch block   
  82.             e.printStackTrace();   
  83.         }   
  84.            
  85.         System.out.println(this.name+"8:40到公司吃饭");   
  86.         try {   
  87.             int a=(int) ((long)1000* Math.random());   
  88.             System.out.println(a);   
  89.             Thread.sleep(a);   
  90.         } catch (InterruptedException e) {   
  91.             // TODO Auto-generated catch block   
  92.             e.printStackTrace();   
  93.         }   
  94.            
  95.         System.out.println(this.name+"8:50打开电脑发呆");   
  96.         try {   
  97.             int a=(int) ((long)1000* Math.random());   
  98.             System.out.println(a);   
  99.             Thread.sleep(a);   
  100.         } catch (InterruptedException e) {   
  101.             // TODO Auto-generated catch block   
  102.             e.printStackTrace();   
  103.         }   
  104.         System.out.println(this.name+"9:00开始工作");   
  105.     }   
  106.   
  107. }  
package wjj2;

public class SomeBody {
	
	private String name;
    public SomeBody(String name)
	{
		this.name=name;
	}
    
    public void someBodyDo()
    {
    	System.out.println(this.name+"早上7:45起床");
    	//随机生成停顿时间,为了模拟较长的代码执行时间,以下都是类似
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    	System.out.println(this.name+"7:50大便");
    	
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    	System.out.println(this.name+"8:00刷牙,顺带刷刷舌苔");
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    	System.out.println(this.name+"8:05洗脸");
    	
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	System.out.println(this.name+"8:10搽雪花膏");
    	
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	System.out.println(this.name+"8:20到车站");
    	
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	System.out.println(this.name+"8:30搭上车");
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    	System.out.println(this.name+"8:40到公司吃饭");
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    	System.out.println(this.name+"8:50打开电脑发呆");
    	try {
    		int a=(int) ((long)1000* Math.random());
    		System.out.println(a);
			Thread.sleep(a);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	System.out.println(this.name+"9:00开始工作");
    }

}

   

 

有“打乱”代码执行顺序能力的Thead子类:SomeBodyWork类:

 

Java代码 复制代码
  1. package wjj2;   
  2.   
  3. public class SomeBodyWork extends Thread{   
  4.     private SomeBody person;   
  5.     public SomeBodyWork (SomeBody person)   
  6.     {   
  7.         this.person=person;   
  8.     }   
  9.   
  10.     public void run()   
  11.     {   
  12.         person.someBodyDo();   
  13.     }   
  14.   
  15. }  
package wjj2;

public class SomeBodyWork extends Thread{
	private SomeBody person;
	public SomeBodyWork (SomeBody person)
	{
		this.person=person;
	}

	public void run()
	{
		person.someBodyDo();
	}

}

 

 

 

程序入口类:main类:

Java代码 复制代码
  1. package wjj2;   
  2.   
  3. public class main {   
  4.     public static void main(String args[])   
  5.     {   
  6.         SomeBody xiaoming=new SomeBody("小明 ");   
  7.         SomeBodyWork thread1=new SomeBodyWork(xiaoming);   
  8.         thread1.start();   
  9.         SomeBody  dagang=new SomeBody("大刚 ");   
  10.         SomeBodyWork thread2=new SomeBodyWork(dagang);   
  11.         thread2.start();   
  12.     }   
  13.   
  14. }  
package wjj2;

public class main {
	public static void main(String args[])
	{
		SomeBody xiaoming=new SomeBody("小明 ");
		SomeBodyWork thread1=new SomeBodyWork(xiaoming);
		thread1.start();
		SomeBody  dagang=new SomeBody("大刚 ");
		SomeBodyWork thread2=new SomeBodyWork(dagang);
		thread2.start();
	}

}

 

程序执行结果如下:

 

 

Java代码 复制代码
  1. 小明 早上745起床   
  2. 571  
  3. 大刚 早上745起床   
  4. 908  
  5. 小明 750大便   
  6. 395  
  7. 大刚 750大便   
  8. 583  
  9. 小明 800刷牙,顺带刷刷舌苔   
  10. 509  
  11. 小明 805洗脸   
  12. 25  
  13. 大刚 800刷牙,顺带刷刷舌苔   
  14. 224  
  15. 小明 810搽雪花膏   
  16. 962  
  17. 大刚 805洗脸   
  18. 292  
  19. 大刚 810搽雪花膏   
  20. 665  
  21. 小明 820到车站   
  22. 554  
  23. 大刚 820到车站   
  24. 278  
  25. 大刚 830搭上车   
  26. 934  
  27. 小明 830搭上车   
  28. 577  
  29. 小明 840到公司吃饭   
  30. 238  
  31. 小明 850打开电脑发呆   
  32. 812  
  33. 大刚 840到公司吃饭   
  34. 453  
  35. 大刚 850打开电脑发呆   
  36. 361  
  37. 小明 9:00开始工作   
  38. 大刚 9:00开始工作  
小明 早上7:45起床
571
大刚 早上7:45起床
908
小明 7:50大便
395
大刚 7:50大便
583
小明 8:00刷牙,顺带刷刷舌苔
509
小明 8:05洗脸
25
大刚 8:00刷牙,顺带刷刷舌苔
224
小明 8:10搽雪花膏
962
大刚 8:05洗脸
292
大刚 8:10搽雪花膏
665
小明 8:20到车站
554
大刚 8:20到车站
278
大刚 8:30搭上车
934
小明 8:30搭上车
577
小明 8:40到公司吃饭
238
小明 8:50打开电脑发呆
812
大刚 8:40到公司吃饭
453
大刚 8:50打开电脑发呆
361
小明 9:00开始工作
大刚 9:00开始工作

 

 

通常Somebody自成一个单独的类,线程的目的就是:让 Somebody 并发地 doSomething

从程序的结果来看:

 1.两个线程的代码确实像图1一样,交替执行,且交替顺序是随机的,多试几次会发现执行结果会有不同。

 2.线程的run()方法提供了一种机制,一种把代码执行顺序“打乱”的机制,有些初学者喜欢在这个提供这个机制的类中,写一下“实体”类的方法,比如,他会让SomeBody类在SomeBodyWork中做一些事情,如

Java代码 复制代码
  1. System.out.println(this.name+"早上10:00开始编码");    
  2. System.out.println(this.name+"早上11:00开始测试");    
  3. System.out.println(this.name+"下午14:45开始修改代码");  
    	System.out.println(this.name+"早上10:00开始编码"); 
    	System.out.println(this.name+"早上11:00开始测试"); 
    	System.out.println(this.name+"下午14:45开始修改代码");

 

 

 

 虽然Java中,什么东西都是对象,什么东西都以对象的模板“类”来展现,但类和类之间,还是有区别的,

很显然,以上3行代码,还是属于“实体”这些类的方法,应该移植在“实体”类中,Thread这个类,提供了一种机制,这种机制用“类”来展现,很神奇吧,呵呵。所以最好不要把杂七杂八的东东放在Thread的子类中,就是一个run()最好,Thread就是纯粹用来“并发”地run的。关于代码的归类,可以参考《重构--改善既有代码的设计》,Martin Fowler著,侯捷,熊节译,中国电力出版社。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值