`
368_fantastic
  • 浏览: 93638 次
  • 性别: Icon_minigender_1
  • 来自: 黑龙江省
社区版块
存档分类
最新评论

Java多线程(一)

阅读更多

一、多线程的概念

 

    我们将正在执行的程序称为进程,现在的计算机大部分都支持多进程体制。例如我们在上网的同时,还可以边听音乐或者边看视频。在只有一个CPU的电脑上,是无法同时运行多个进程的,而是CPU轮流执行多个程序,看上去像是多个进程在同时执行。

 

    上面是多进程的例子。但是,我们在程序内部,也可以同时运行多个任务,我们将在一个进程内部运行的每一个任务都称为一个线程(Thread)。在某个时间点上,CPU运行的线程只能有一个。

 

二、线程的使用范围

 

    多线程应用无处不在,但应用最频繁的是游戏开发和网络编程。

 

三、如何创建线程:

 

    在Java中,线程也是一种对象,但并非任何对象都可以成为线程,只有实现了Runnable接口的类才可以称为线程。我们可以通过两种方式来创建一个线程对象。

 

    (1)让一个类实现Runnable接口,实现该接口的run()方法

package buaa.threaddemo;

public class ThreadDemo implements Runnable{

	/**
	 * 实现了Runnable的run()方法,这个方法是在线程对象获得CPU的使用权的时候真正运行的方法,
	 * 系统会自动调用的,我们无需直接调用run()方法。
	 */
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println("---->"+Thread.currentThread().getName()+i);
		}
	}

	public static void main(String[] args) {
		//创建一个ThreadDemo对象
		ThreadDemo threadDemo = new ThreadDemo();
		//创建线程对象thread1,并给线程thread1起个名字
		Thread thread1 = new Thread(threadDemo,"线程一");
		//创建线程对象thread2,没有给线程对象thread2起名字,所以系统会提供默认的名字,即Thread-编号
		Thread thread2 = new Thread(threadDemo);
		//启动一个线程,注意:启动线程的方式是通过Thread类的start()方法来启动一个线程
		thread1.start();
		//启动另一个线程
		thread2.start();
	}
}

    注:Thread.currentThread().getName()的作用是得到当前线程的名字。

 

    (2)让一个类继承java.lang.Thread类,由于Thread类本身已经实现了Runnable接口,所以通过继承该类,也可以将一个普通类转变为线程类。

package buaa.threaddemo;

public class ThreadDemo2 extends Thread{

	public void run(){
		for (int i = 0; i < 100; i++) {
			System.out.println("---->"+i);
		}
	}
	
	public static void main(String[] args) {
		//创建一个ThreadDemo2对象
		ThreadDemo2 threadDemo = new ThreadDemo2();
		//启动线程
		threadDemo.start();
	}

}

    两种创建线程的方式对比分析:

 

    既然直接继承Thread类和实现Runnable接口都能实现多线程,那么这两种实现多线程的方式在应用上有什么区别吗?我们到底用哪个好呢?

 

    为了回答这个问题我们通过编写一个应用程序来进行分析比较。我们用程序来模拟铁路售票系统,实现通过4个售票点发售某日某次列车的100张车票,一个售票点用一个线程来表示。

package buaa.threaddemo;

public class ThreadSellTicket extends Thread{
	
	private int tickets = 100;
	
	public void run(){
		
		while (tickets > 0) {
			
			String threadName = Thread.currentThread().getName();
			
			System.out.println(threadName + "is saling ticket " + tickets--);
		}
	}
}

package buaa.threaddemo;

public class ThreadTest {

	public static void main(String[] args) {
		
		ThreadSellTicket thread = new ThreadSellTicket();
		thread.start();
		thread.start();
		thread.start();
		thread.start();
	}
}

   在上面代码中,我们用ThreadSellTicket类模拟售票处的售票过程,run方法的每次循环都将总票数减一,模拟卖出一张车票,同时将该车票号打印出来,直到剩余票数为0为止。在ThreadTest类的main方法中,我们创建了一个线程对象,并重复启动四次,希望通过这个方式产生四个线程,结果怎样呢?

 

    从运行结果上看,我们发现其实只有一个线程在运行,这个结果告诉我们:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果都只有一个线程

   

   我们接着修改ThreadTest,在main方法中创建四个ThreadSellTicket对象:

package buaa.threaddemo;

public class ThreadTest {

	public static void main(String[] args) {
		
		ThreadSellTicket thread1 = new ThreadSellTicket();
		ThreadSellTicket thread2 = new ThreadSellTicket();
		ThreadSellTicket thread3 = new ThreadSellTicket();
		ThreadSellTicket thread4 = new ThreadSellTicket();
		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
	}
}
部分运行结果:
Thread-0is saling ticket 98
Thread-0is saling ticket 97
Thread-0is saling ticket 96
Thread-3is saling ticket 99
Thread-2is saling ticket 83
Thread-1is saling ticket 99
Thread-2is saling ticket 82

    从上面结果上看,每个票号都被打印了四遍,即四个线程各自卖各自的100张票,而不是去卖共的100张票。

 

   这种情况是怎样造成的呢?我们需要的是,多个线程去处理同一资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadSellTicket对象,就等于创建了四个资源,每个ThreadSellTicket都有100张票,每个线程在独立的处理各自的资源。

 

     经过分析,我们可以总结出,要实现这个铁路售票模拟程序,我们只能创建一个资源对象,但要创建多个线程去处理这同一资源对象,并且每个线程上所运行的都是相同的代码。

package buaa.threaddemo;

public class ThreadSellTicket2 implements Runnable{

	private int tickets = 100;
	public void run() {
		while (tickets > 0) {
			String threadName = Thread.currentThread().getName();
			System.out.println(threadName + "is saling ticket " + tickets--);
		}
	}
}

package buaa.threaddemo;

public class ThreadTest {

	public static void main(String[] args) {
		ThreadSellTicket2 tickets = new ThreadSellTicket2();
		Thread thread1 = new Thread(tickets);
		Thread thread2 = new Thread(tickets);
		Thread thread3 = new Thread(tickets);
		Thread thread4 = new Thread(tickets);
		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
	}
}

    在上面程序中,我们创建了四个线程,每个线程调用的是同一个ThreadSellTicket2对象中的run()方法,访问的是同一个对象中的变量(tickets)的实例,这个程序满足了我们的需求。

 

    可见,实现Runnable接口相对于继承Thread类来说,有如下好处:

 

    1、适合多个相同程序代码的线程去处理同一资源的情况,把线程同程序代码,数据有效分离,较好的体现了面向对象的设计思想。

 

    2、可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式。

 

 

分享到:
评论

相关推荐

    Java多线程设计模式上传文件

    Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    java多线程ppt

    java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题

    java 多线程操作数据库

    一个java 多线程操作数据库应用程序!!!

    java多线程的讲解和实战

    详细的讲解了java多线程的原理,并配有代码进行实战,适合java初学者和想对多线程有进一步了解的人。

    java多线程经典案例

    java多线程经典案例,线程同步、线程通信、线程阻塞等经典案例

    多线程启动.java多线程启动.java多线程启动.java

    多线程启动.java多线程启动.java多线程启动.java多线程启动.java

    java多线程查询数据库

    java多线程并发查询数据库,使用线程池控制分页,并发查询。

    Java多线程知识点总结

    该文档总结了Java多线程相关的知识点,分享给大家,简单易懂!

    java多线程处理数据库数据

    java多线程处理数据库数据,使用并发包,无框架,可批量处数据库数据,进行增删改。。等等操作。

    java多线程核心技术

    资深Java专家10年经验总结,全程案例式讲解,首本全面介绍Java多线程编程技术的专著 结合大量实例,全面讲解Java多线程编程中的并发访问、线程间通信、锁等最难突破的核心技术与应用实践 Java多线程无处不在,如...

    Java多线程编程经验

    现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 线程是指进程中的一个执行流程,一个进程中可以运行多个线程。...本文档提供Java多线程编程经验,方便广大Java爱好者研究学习Java多线程

    java多线程进度条

    java多线程进度条

    java多线程处理大数据

    java多线程处理大数据,可根据配置的线程数,任务去调度处理

    java多线程通信图解

    一张图方便理解和掌握java 多线程之间通信的实质 java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,...

    java多线程,对多线程,线程池进行封装,方便使用

    java多线程,对多线程,线程池进行封装,方便使用

    Java多线程实现异步调用实例

    Java多线程实现异步调用实例。运行Main可以看到结果。main是主线程,另有A,B,C三个线程用不同的时间跑完。

    Java多线程编程实战指南(核心篇)

    Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...

    java多线程实现大批量数据导入源码

    java多线程实现大批量数据切分成指定份数的数据,然后多线程处理入库或者导出,线程的个数和每份数据的数量都可以控制

    java多线程并发

    java多线程并发的在新窗口

Global site tag (gtag.js) - Google Analytics