`

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
分享到:
评论

相关推荐

    day11-多线程 java

    day11-多线程 java

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

    多线程简单工厂设计模式,工厂方法模式,单列模式,多线程死锁解决

    达内Java培训-CoreJava全程笔记(WORD唐亮版)

    CoreJava DAY01 Java概述 1 CoreJava DAY02 数据类型和控制结构 6 CoreJava DAY03 数组 11 CoreJava DAY04 15 ...CoreJava DAY19-20 多线程 85 CoreJava DAY21-22 IO 95 CoreJava DAY23 网络编程 107

    java_diary_18.rar_JFC_swing_反射机制_国际化 java

    Day11:多线程-进程与线程及方法 Day12:线程机制与I/O流的方法 Day13:I/O流的类与编码方式 Day14:优化的I/O流与网络编程 Day15:网络编程与常用类库 Day16:国际化与新特性 Day17:新特性与并发线程 Day18:软件...

    达内 CoreJava老师笔记汇总

    CoreJava DAY01 Java概述 1 CoreJava DAY02 数据类型和控制结构 10 CoreJava DAY03 数组 20 CoreJava DAY04 27 ...CoreJava DAY19-20 多线程 154 CoreJava DAY21-22 IO 174 CoreJava DAY23 网络编程 197

    CoreJava笔记

    CoreJava笔记 CoreJava DAY01 Java概述 1 CoreJava DAY02 数据类型和控制结构 6 CoreJava DAY03 数组 11 CoreJava DAY04 15 ...CoreJava DAY19-20 多线程 85 CoreJava DAY21-22 IO 95 CoreJava DAY23 网络编程 107

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

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

    day11-多线程(1)1

    1.1进程和线程【理解】 1.2实现多线程方式一:继承Thread类【应用】 1.3设置和获取线程名称【应用】 1.4线程优先级【应用】 1.5线程控制【应用】

    python多线程DAY05.txt

    多进程/多线程并发 : 任何任务 3. 基于fork的多进程并发程序 每当有一个客户端连接就创建一个新的进程 4. ftp文件服务程序 *********************************************** 多线程并发 threading 的多...

    day01-java基础语法.pdf

    Java是一门面向对象编程...Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 [2] 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等 [3] 。

    python多线程DAY04.txt

    解决了多个进程或者线程对共享资源的争夺 Event e.set e.clear e.wait Lock lock.acquire() lock.release() 4. 什么是线程 threading Thread() t.start() t.join() t.name t.getName t.setName t.daemon...

    java学习文档(快速学习-非常使用)

    Day1 一、 从面向过程编程到面向对象编程的思维转变 二、 什么是字节码和虚拟机: 三、 环境变量的设置 四、 kate工具的使用 五、 我们的第一个Java...《多线程》 Day12 一.I/O 流(java 如何实现与外界数据的交流)

    python多线程DAY01.txt

    1.epoll模型 : 效率高 , 触发方式更多 2.本地套接字 AF_UNIX 本地两个进程间的消息通信 3.多任务编程 * 并行 和 并发 * 进程 线程 4. 多进程编程 时间片 PCB PID 父子进程 优先级 进程特征 进程状态: 就绪态 ...

    python多线程DAY02.txt

    1. 如何处理僵尸进程 * 通过wait waitpid * 通过创建二级子进程,让一级子进程退出 2. multiprocessing创建进程 * Process 类 创建进程对象 * 通过start启动进程 * 通过join回收子进程 **********************...

    python多线程DAY03.txt

    1. 进程对象属性 p.pid p.name p.is_alive() p.daemon 2. 自定义进程类 继承Process 重写run 3. 进程池 大量进程事件需要频繁创建删除进程 Pool() apply_async() close() join() map() 4.进程间通信 ...

    java视频教程Day01 免费

    11. Multi-Thread(多线程) 12. I/O and File (输入/输出流及文件) 13. Networking (网络编程) 以上教学过程中贯穿一个银行项目,根据每天所学的东西不断完善 J2EE部分 14. JDBC Overview and Using JDBC ...

    python学习day07.txt

    1、多线程爬虫 1、多进程线程应用场景 1、多进程 :大量密集并行计算 2、多线程 :I/O密集(网络I/O、本地磁盘I/O) 2、多线程爬虫 1、URL队列 :put(url) 2、RES队列 :从URL队列中get()发请求,put(html) 3、...

    Java 2实用教程(第三版)实验指导与习题解答

    上机实践8 多线程 41 实验1 汉字打字练习 41 实验2 旋转的行星 43 实验3 双线程接力 47 上机实践9 输入输出流 50 实验1 学读汉字 50 实验2 统计英文单词字 53 实验2 读取Zip文件 56 上机实践10 Java 中的网络编程 57...

    达内 coreJava 习题答案

    1 1 2 3 5 8 13 21 34 规律:一个数等于前两个数之和 //计算斐波那契数列(Fibonacci)的第n个值 public class Fibonacci{ public static void main(String args[]){ int n = Integer.parseInt(args[0]); int n1 ...

Global site tag (gtag.js) - Google Analytics