`

day_34Java多线程1

阅读更多

星期五, 十二月 04, 2015 19:40:55

 

 

一、进程和线程

 

采用Java的多线程机制可以使计算机资源得到更充分的使用,多线程可以使程序在同一时间内完成很多操作。

 

       本章讲解 进程与线程的共同点和区别、实现多线程的方法、线程的状态、对线程操作的方法、多线程的同步、线程间的通信,

以及线程生命周期的控制等内容。

        本章要点:

              了解进程和线程

               掌握实现多线程的方法

               熟悉线程的状态

               熟悉线程操作的方法

               熟悉线程同步的方法

               熟悉线程间通信的方法

 

      Java是少数的几种支持“多线程”的语言之一。

     大多数的程序语言只能循序运行单独的一个程序块,但无法同时运行不同的多个程序块。

     

          Java的“多线程”恰可弥补这个遗憾,它可以让不同的程序块一起运行,

   如此一来就可让程序运行的更为顺畅,同时也可达到多任务处理的目的。

 

   进程的特征是:

 

           1.一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源。

     在进行概念中,每一个进程的内部数据和状态都是完全独立的。

           2.创建并执行一个进程的系统开销比较大。

           3.进程是程序的一次执行过程,是系统运行程序的基本单位。

     

   线程的特征是:

   

         1.在java中,程序通过流控制来执行程序流。程序中单个顺序的流控制称为线程。

         2.多线程指的是在单个进行中可以同时运行多个不同的线程,执行不同的任务。

多线程意味着一个程序的多行语句可以看上去几乎同时运行。

 

    二者都是一段完成某个特定功能的代码,是程序中单个顺序的流控制。

 

         不同的是同类的多个线程是共享一块内存空间和一组系统资源,

而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。

所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小得多,正因为如此,线程也被

称为轻负荷进程。一个进程中可以包含多个线程。

 

      多线程是实现并发机制的一种有效手段。

进程和线程一样,都是实现并发的一个基本单位。

线程和进程的只要差别体现在以下两个方面。

  1.同样作为基本的执行单元,线程是划分得比进程更小的执行单位。

  2.每个进程都有一段专用的内存区域。与此相反,线程却共享内存单元(包括代码和数据),

 

通过共享的内存单元来实现数据交换、实时通信与必要的同步操作。

 

         多线程的应用范围很广。在一般情况下,程序的某些部分同待定的事件或资源联系在一起,同时又不想为它而

暂停程序其他部分的执行,在这种情况下,就可以考虑创建一个线程,令它与那个事件或资源关联到一起,并让它

独立于主程序运行。

通过使用线程,可以避免用户在运行程序和得到结果之间的停顿,还可以让一些任务(如打印任务)在后台运行,

而用户则在前台继续完成一些其他的工作。

      总之,利用多线程技术,可以使编程人员方便的开发出能同时处理多个任务的功能强大的应用程序。

 

 

二、认识线程

     

    2.1.所谓线程(Thread)是指程序的运行流程,“多线程”的机制则是指可以同时运行多个程序块,使程序运行的效率变得更高,

也可克服传统程序语言所无法解决的问题。

   例如,有些包含循环的线程可能要使用比较长的一段时间来运行,此时便可让另一个线程来做其他的处理。

 

   2.2本节用一个程序来说明单一线程与多线程的不同。

      Demo1是单一线程的范例。

 

   
       2.2.2代码案例1

package day34;

public class ThreadDemo1 {
	//单一线程,只有等Thread运行完才可以运行main()
	public static void main(String[] args) {
		Thread td = new Thread();
		td.run();
		System.out.print("\n");
		for(int i=0;i<5;i++) {
			System.out.print("main()..."+i+"\t");
		}
	}
}

class Thread {
	public void run() {
		for(int i = 0;i<5;i++) {
			System.out.print("Thread ..."+i+"\t");
		}
	}
}

 运行结果:

 

Thread ...0Thread ...1Thread ...2Thread ...3Thread ...4

main()...0main()...1main()...2main()...3main()...4

 

 

2.2.2代码案例2

    在java里,是否可以同时运行,交替输出。其方法是--在java里激活多线程。

    

    如何激活线程:

   如果在类里要激活线程,必须先做好下面的两个准备

       1.线程必须扩展自Thread类,使自己成为它的子类。

       2.线程的处理必须编写在run()方法内。

 

 

2.3通过继承Thread类实现多线程

   Thread存放在java.lang类库中。run()方法是定义在Thread类里的一个方法,因此把线程的程序代码编写在run()方法内,

事实上所做的就是覆写的操作。

   因此要使一个类可激活线程,必须按照下面的格式:

     class 类名称 extends Thread{ //从Thread类扩展出子类

       属性...

       方法...

       修饰符 run() {             //覆写Thread类里的run()方法

         以线程处理的程序;

       }

     }

 

2.3.1代码案例

 

package day34;
import java.lang.Thread;

public class ThreadDemo2 {
	public static void main(String[] args) {
		/*使用线程最大的问题就是不可确定性。
		 * 线程运行是,谁先拿到锁,谁先运行,没先后之分的。*/
		Thread2 td2 = new Thread2();
		td2.start();
		
		for(int i=0;i<3;i++) {
			System.out.print("main..."+i+"\t");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
/*如果在类里要激活线程,必须先做好下面的两个准备
 *1.线程必须扩展自Thread类,使自己成为它的子类。
 *2.线程的处理必须编写在run()方法内。*/
class Thread2 extends Thread{
	//java.lang.Thread
	@Override
	public void run() {
		for(int i =0;i<3;i++){
			System.out.print("Thread2..."+i+"\t");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}


运行结果:
main...0	Thread2...0	Thread2...1	main...1	Thread2...2	main...2	

 注意:

 

    1.就不应该是交替显示,cpu分配给各个线程的执行时间是不确定的,另外每个线程也有优先级别

    2.使用线程最大的问题就是不可确定性。线程运行是,谁先拿到锁,谁先运行,没先后之分的。

 

 

2.4 通过实现Runnable接口实现多线程

    在java中如果一个类继承了某一个累 ,同时又想采用多线程技术的时候,就不能用Thread类产生线程,

因为java不允许多继承,这时要用Runnable接口来实现创建线程。

    格式:

     class 类名称 implements Runnable { //实现Runnable接口

        属性...

        名称...

        修饰符 run(){      //覆写Thread类里的run()方法

        以线程处理的程序;  

        }

     }

 

 

2.4.1用Runnable接口实现多线程使用实例

代码案例:

package day34;

public class ThreadRunnable {
	public static void main(String[] args){
		Thread3 td3 = new Thread3();
		@SuppressWarnings("unused")
		/*Thread(Runnable target) 分配新的 Thread 对象。
		 * 因为Runnable接口没start()方法,所以要通过Thread来启动多线程
		 */
		Thread td4 = new Thread(td3);
		td4.start();
		
		for(int i =0;i<3;i++) {
			System.out.print("main..."+i+"\t");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}


//
class Thread3 implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i =0 ;i<3;i++) {
			System.out.print("Thread3..."+i+"\t");
		}
	}
	
}

 

运行结果:

main...0Thread3...0Thread3...1Thread3...2main...1main...2

注意:

    1.将一个Runnable接口的实例化对象作为参数去实例化Thread类对象。

    2.在实际的开发中,尽可能地使用Runnable接口去实现多线程机制。

 

三、两种多线程实现机制的比较

 

1.java.lang.Thread 所已实现的接口: Runnable

2.区别:

  通过编写一个应用程序来比较分析。

 

3.代码案例

 

模拟铁路售票系统的范例,实现4个售票发售某日某次列车的车票20张,一个售票点用一个线程来表示。

 

 

星期日, 十二月 06, 2015   14:17:38

 

星期日, 十二月 06, 2015  16:17:08

首先用继承Thread类来实现这个程序。

 

currentThread() 

          返回对当前正在执行的线程对象的引用。

 

3.1代码案例:

package day34;

public class ThreadDemo4 {
	public static void main(String[] args) {
		/*模拟铁路售票系统的范例,实现4个售票发售某日某次列车的车票20张,
		一个售票点用一个线程来表示。*/
		Thread5 th5 = new Thread5();
		//一个线程对象只能启动一次
		th5.start();
		th5.start();
		th5.start();
		th5.start();
	}

}
class Thread5 extends Thread {
	private int tickets = 20;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			if(tickets>0) {
			System.out.println(Thread.currentThread().getName()+"..."+(tickets--));
			}
		}
	}
}

 运行结果:

Thread-0...20

Thread-0...19

Thread-0...18

Thread-0...17

Thread-0...16

Thread-0...15

Thread-0...14

Thread-0...13

Thread-0...12

Thread-0...11

Thread-0...10

Thread-0...9

Thread-0...8

Thread-0...7

Thread-0...6

Thread-0...5

Thread-0...4

Thread-0...3

Thread-0...2

Thread-0...1

Exception in thread "main" java.lang.IllegalThreadStateException

at java.lang.Thread.start(Thread.java:595)

at day34.ThreadDemo4.main(ThreadDemo4.java:10)

 

注意:

    1.创建了TestThrea类的实例化对象,之后调用了4此start()方法。

但从运行的结果可知,程序运行时出现了异常,之后却只有一个线程在运行。

     2.这 说明了一个类继承Thread类之后,这个类的对象无论调用多少次start()方法,结果只有一个线程在运行。

     3.Thread.currentThread().getName()取得当前运行的线程名称。

 

3.2代码案例:

   启动4个线程,分别进行各自的操作

package day34;

public class ThreadDemo5 {
	public static void main(String[] args) {
		/*模拟铁路售票系统的范例,实现4个售票发售某日某次列车的车票20张,
		一个售票点用一个线程来表示。*/
		
		//启动4个线程,分别进行各自的操作
		new Thread6().start();
		new Thread6().start();
		new Thread6().start();
		new Thread6().start();
		
	}

}
class Thread6 extends Thread {
	private int tickets = 20;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			if(tickets>0) {
			System.out.println(Thread.currentThread().getName()+"..."+(tickets--));
			}
		}
	}
}

 运行结果:

Thread-0...20

Thread-0...19

Thread-0...18

Thread-2...20

Thread-0...17

Thread-0...16

Thread-0...15

Thread-0...14

Thread-0...13

Thread-0...12

Thread-3...20

Thread-2...19

................

 

 

注意:

     1.启动4个线程对象,但这4个线程对象各自占有各自的资源,所以:用Thread类实际上无法达到资源共享的目的。

 

3.3代码案例: 用Runnable接口实现多线程使用

package day34;

public class ThreadDemo6 {
	public static void main(String[] args) {
		/*模拟铁路售票系统的范例,实现4个售票发售某日某次列车的车票20张,
		一个售票点用一个线程来表示。*/
		Thread6 td6 = new Thread6();
		//启动4个线程,并实现了资源共享的目的
		new Thread(td6).start();
		new Thread(td6).start();
		new Thread(td6).start();
		new Thread(td6).start();
		
	}

}
class Thread6 implements Runnable {
	private int tickets = 20;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			if(tickets>0) {
			System.out.println(Thread.currentThread().getName()+"..."+(tickets--));
			}
		}
	}
}

 运行结果:

Thread-2...20

Thread-3...19

Thread-2...18

Thread-3...17

Thread-2...16

Thread-3...15

Thread-2...14

Thread-3...13

Thread-2...12

Thread-3...11

Thread-2...10

Thread-3...9

Thread-2...8

Thread-3...7

Thread-2...6

Thread-3...5

Thread-2...4

Thread-3...3

Thread-2...2

Thread-3...1

 

注意:

    1.启动4个线程,但结果都是操纵同一资源,从而实现了资源共享的目的。

 

 

 

3.4总结

实现Runnable接口相对于继承Thread类来说,有以下优势:

    1.适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,

较好的体现了面向对象的设计思想。

    2.可以避免由于java的单继承特性带来的局限。

开发中经常会碰到这样一种情况,即要将已经继承了某一个子类放入多线程中,由于一个类不能同时有两个父类,

所以不能使用继承Thread类的方式,那么就只能采用实现Runnable接口的方式。

   3.增强了程序的健壮性,代码能够被多个线程共享,代码与数据时独立的。

当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程可以操作相同的数据,与它们的代码无关。

当共享访问相同的对象时,即共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造方法实参传递进去,

这个对象就是一个实现了Runnable接口的类和实例。

 

   事实上,几乎所有的多线程应用都应用实现Runnable接口。

 

星期日, 十二月 06, 2015 17:35:10

0
1
分享到:
评论

相关推荐

    day02_eesy_01anno_ioc_多线程_

    本课程“day02_eesy_01anno_ioc_多线程”主要聚焦于Spring框架的核心特性——IOC(Inversion of Control,控制反转)以及其在多线程环境下的应用。 首先,让我们深入理解什么是IOC。控制反转是一种设计模式,它将...

    day17_线程创建、线程同步、线程状态.pdf

    Java多线程编程基础知识点 本节课主要讲解了Java多线程编程的基础知识,包括线程的概念、线程与进程的区别、多线程的随机性、Java程序的进程中的线程、线程的创建方式、线程的执行流程、线程内存图等。 1. 进程与...

    day14_多线程01.zip

    本资源“day14_多线程01.zip”可能是某个教学课程或者学习资料的一部分,着重讲解了多线程的基础知识和应用。虽然没有具体的标签提供额外信息,但我们可以根据标题和描述来深入探讨多线程这一主题。 多线程是指在一...

    day15_多线程02.zip

    "day15_多线程02"这个标题暗示我们将会深入探讨多线程的第二部分,这可能是一个课程或者教程的第十五天内容,重点在于多线程的进阶主题。尽管没有具体的标签,我们可以假设这个压缩包可能包含了源代码、笔记、示例或...

    day11-多线程 java

    day11-多线程 java

    day13_StringBuffer_java_

    在Java编程语言中,"StringBuffer" 是一个非常重要的类,尤其在处理字符串操作时,尤其是在多线程环境中。在本教程"day13_StringBuffer_java_"中,我们将深入探讨这个类及其在Java中的作用。 Java是C++的优化版本,...

    GSDN_day_01.pdf

    Java的特点包括面向对象、简单性、解释性、高性能、分布式处理、多线程、健壮性、动态、结构中立和安全性等。 Java的简单性体现在它语法上的简洁,对于程序设计来说较为直观易学。解释性指的是Java程序在执行前需要...

    传智博客_Java培训_毕向东_Java基础课件

    4. **多线程**(传智播客_Java培训_毕向东_Java基础[05-多线程].pdf):Java提供了强大的并发支持,多线程编程是其特色之一。这里会涉及线程的创建、同步、协作以及线程安全问题的处理。 5. **集合**(传智播客_...

    多线程-day02.docx

    在“多线程-day02”的学习资源中,我们深入探讨了Java内存模型以及多线程的特性与控制机制。 **Java内存模型** Java内存模型,也称为JVM内存模型,是Java程序员理解和掌握的基础知识,特别是在进行并发编程时。它...

    java多线程代码笔记

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,从而提高系统效率和资源利用率。在Java中,实现多线程有两种主要方式:通过实现`Runnable`接口和继承`Thread`类。 首先,让我们从创建线程开始。当...

    day24-多线程-设计模式.7z

    在本课程"day24-多线程-设计模式"中,我们将深入探讨如何利用多线程结合设计模式来优化程序执行效率。首先,我们要理解的是,多线程是指在一个进程中同时执行多个线程,从而使得程序能够同时处理多个任务,提升系统...

    JavaSE基础入门视频教程33天之(26) part2

    接着,“day26_21(多线程)JDK5实现线程池.avi”将介绍Java 5及更高版本引入的线程池概念。线程池可以优化系统资源的使用,通过复用已创建的线程来减少创建和销毁线程的开销。Executor框架中的ThreadPoolExecutor是...

    多线程,day2,B站狂神,代码Lesson.rar

    "多线程,day2,B站狂神,代码Lesson.rar"这个资源可能是一个关于Java多线程的第二日课程,由B站(哔哩哔哩)上的一位知名编程讲师,也就是所谓的“狂神”,分享的教学材料,包含有实际的代码示例。 首先,我们来...

    day13_tomcat_java_

    总的来说,Java Web开发中,Tomcat的学习涵盖了服务器的安装、应用部署、Servlet与JSP编程、错误处理以及性能优化等多个方面。通过深入理解和实践,你将能够熟练地利用Tomcat搭建和管理Java Web应用。

    Wiley_Java in 60 Minutes a Day_2003

    8. **多线程**:学习如何创建和管理线程,理解同步和互斥的概念,以及如何避免线程安全问题。 9. **文件和目录操作**:了解如何在Java中进行文件和目录的创建、删除、重命名等操作。 10. **Java API的使用**:书中...

    java多线程

    Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,极大地提升了程序的效率和响应性。在Java中,多线程主要通过两种方式实现:继承Thread类和实现Runnable接口。下面将深入探讨Java多线程的底层原理、...

    Java_day17上课资料.zip

    线程间的通信和同步是多线程编程中的关键点,例如使用synchronized关键字实现互斥访问,或者使用wait()、notify()和notifyAll()方法控制线程的执行顺序。 此外,文件和I/O操作也是Java开发者必备的技能。Java提供了...

    多线程-day01.docx

    在 Java 中,多线程是并发编程的重要概念,它允许程序同时执行多个任务,从而提高系统效率和资源利用率。在本教程中,我们将探讨多线程的基础知识,包括并发与并行的区别,进程与线程的概念,以及如何在 Java 中创建...

    basic_day01_v1_pm_all.zip

    10. **多线程**:理解线程的概念,如何创建并运行线程,以及同步和互斥的概念。 以上是Java基础知识的一部分,对于初学者来说,掌握这些内容是进一步学习Java高级特性和框架的基础。通过"basic_day01_v1_pm_all.zip...

    week4_code_javaprogramming_java_bluej_

    6. **多线程**:Java内置对多线程的支持,可以同时执行多个任务,提升程序效率。 7. **网络编程**:利用Socket编程可以实现客户端和服务器之间的通信。 8. **API和库的使用**:如 Swing 或 JavaFX 用于创建图形用户...

Global site tag (gtag.js) - Google Analytics