大虾,发一些简单的java多线程demo。最好是那种能够让我理解谈谈你对多线程的理解好处的。以及谈谈你对多线程的理解弊端之类的。

Java 多线程编程
Java给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径。
多线程是多任务的一种特别的形式。多线程比多任务需要更小的开销。
这里定义和线程相关的另一个术语:进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。
多线程能满足程序员编写非常有效率的程序来达到充分利用CPU的目的,因为CPU的空闲时间能够保持在最低限度。
一个线程的生命周
线程经过其生命周期的各个阶段。下图显示了一个线程完整的生命周期。
新状态: 一个新产生的线程从新状态开始了它的生命周期。它保持这个状态知道程序start这个线程。
运行状态:当一个新状态的线程被start以后,线程就变成可运行状态,一个线程在此状态下被认为是开始执行其任务
就绪状态:当一个线程等待另外一个线程执行一个任务的时候,该线程就进入就绪状态。当另一个线程给就绪状态的线程发送信号时,该线程才重新切换到运行状态。
休眠状态: 由于一个线程的时间片用完了,该线程从运行状态进入休眠状态。当时间间隔到期或者等待的时间发生了,该状态的线程切换到运行状态。
终止状态: 一个运行状态的线程完成任务或者其他终止条件发生,该线程就切换到终止状态。
线程的优先级
每一个Java线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。Java优先级在MIN_PRIORITY(1)和MAX_PRIORITY(10)之间的范围内。默认情况下,每一个线程都会分配一个优先级NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器时间。然而,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
创建一个线程
Java提供了两种创建线程方法:
通过实现Runable接口;
通过继承Thread类本身。
通过实现Runnable接口来创建线程
创建一个线程,最简单的方法是创建一个实现Runnable接口的类。
为了实现Runnable,一个类只需要执行一个方法调用run(),声明如下:
publicvoid run()
你可以重写该方法,重要的是理解的run()可以调用其他方法,使用其他类,并声明变量,就像主线程一样。
在创建一个实现Runnable接口的类之后,你可以在类中实例化一个线程对象。
Thread定义了几个构造方法,下面的这个是我们经常使用的:
Thread(Runnable threadOb,String threadName);
这里,threadOb 是一个实现Runnable 接口的类的实例,并且 threadName指定新线程的名字。
新线程创建之后,你调用它的start()方法它才会运行。
void start();
下面是一个创建线程并开始让它执行的实例:
// 创建一个新的线程
class NewThread implements Runnable {
NewThread() {
// 创建第二个新线程
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // 开始线程
// 第二个线程入口
public void run() {
for(int i = 5; i & 0; i--) {
System.out.println("Child Thread: " + i);
// 暂停线程
Thread.sleep(50);
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
System.out.println("Exiting child thread.");
public class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // 创建一个新线程
for(int i = 5; i & 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
System.out.println("Main thread exiting.");
编译以上程序运行结果如下:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
通过继承Thread来创建线程
创建一个线程的第二种方法是创建一个新的类,该类继承Thread类,然后创建一个该类的实例。
继承类必须重写run()方法,该方法是新线程的入口点。它也必须调用start()方法才能执行。
// 通过继承 Thread 创建线程
class NewThread extends Thread {
NewThread() {
// 创建第二个新线程
super("Demo Thread");
System.out.println("Child thread: " + this);
start(); // 开始线程
// 第二个线程入口
public void run() {
for(int i = 5; i & 0; i--) {
System.out.println("Child Thread: " + i);
// 让线程休眠一会
Thread.sleep(50);
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
System.out.println("Exiting child thread.");
public class ExtendThread {
public static void main(String args[]) {
new NewThread(); // 创建一个新线程
for(int i = 5; i & 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
System.out.println("Main thread exiting.");
编译以上程序运行结果如下:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Thread 方法
下表列出了Thread类的一些重要方法:
public void start()
使该线程开始执行;Java 虚拟机调用该线程的&run&方法。
public void run()
如果该线程是使用独立的&Runnable&运行对象构造的,则调用该&Runnable&对象的&run&方法;否则,该方法不执行任何操作并返回。
public final void setName(String name)
改变线程名称,使之与参数&name&相同。
public final void setPriority(int priority)
&更改线程的优先级。
public final void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。
public final void join(long millisec)
等待该线程终止的时间最长为&millis&毫秒。
public void interrupt()
中断线程。
public final boolean isAlive()
测试线程是否处于活动状态。
测试线程是否处于活动状态。 上述方法是被Thread对象调用的。下面的方法是Thread类的静态方法。
public static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
public static void sleep(long millisec)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
public static boolean holdsLock(Object x)
当且仅当当前线程在指定的对象上保持监视器锁时,才返回&true。
public static Thread currentThread()
返回对当前正在执行的线程对象的引用。
public static void dumpStack()
将当前线程的堆栈跟踪打印至标准错误流。
如下的ThreadClassDemo 程序演示了Thread类的一些方法:
// 文件名 : DisplayMessage.java
// 通过实现 Runnable 接口创建线程
public class DisplayMessage implements Runnable
public DisplayMessage(String message)
this.message =
public void run()
while(true)
System.out.println(message);
// 文件名 : GuessANumber.java
// 通过继承 Thread 类创建线程
public class GuessANumber extends Thread
public GuessANumber(int number)
this.number =
public void run()
int counter = 0;
int guess = 0;
guess = (int) (Math.random() * 100 + 1);
System.out.println(this.getName()
+ " guesses " + guess);
counter++;
}while(guess != number);
System.out.println("** Correct! " + this.getName()
+ " in " + counter + " guesses.**");
// 文件名 : ThreadClassDemo.java
public class ThreadClassDemo
public static void main(String [] args)
Runnable hello = new DisplayMessage("Hello");
Thread thread1 = new Thread(hello);
thread1.setDaemon(true);
thread1.setName("hello");
System.out.println("Starting hello thread...");
thread1.start();
Runnable bye = new DisplayMessage("Goodbye");
Thread thread2 = new Thread(hello);
thread2.setPriority(Thread.MIN_PRIORITY);
thread2.setDaemon(true);
System.out.println("Starting goodbye thread...");
thread2.start();
System.out.println("Starting thread3...");
Thread thread3 = new GuessANumber(27);
thread3.start();
thread3.join();
}catch(InterruptedException e)
System.out.println("Thread interrupted.");
System.out.println("Starting thread4...");
Thread thread4 = new GuessANumber(75);
thread4.start();
System.out.println("main() is ending...");
运行结果如下,每一次运行的结果都不一样。
Starting hello thread...
Starting goodbye thread...
Thread-2 guesses 27
** Correct! Thread-2 in 102 guesses.**
Starting thread4...
..........remaining result produced.
线程的几个主要概念:
在多线程编程时,你需要了解以下几个概念:
线程间通信
线程控制:挂起、停止和恢复
多线程的使用
有效利用多线程的关键是理解程序是并发执行而不是串行执行的。例如:程序中有两个子系统需要并发执行,这时候就需要利用多线程编程。
通过对多线程的使用,可以编写出非常高效的程序。不过请注意,如果你创建太多的线程,程序执行的效率实际上是降低了,而不是提升了。
请记住,上下文的切换开销也很重要,如果你创建了太多的线程,CPU花费在上下文的切换的时间将多于执行程序的时间!
关注微信下载离线手册java多线程的好处,面试常问到的
1. 充分利用CPU资源
现在世界上大多数计算机只有一块CPU.因此,充分利用CPU资源显得尤为重要。当执行单线程程序时,由于在程序发生阻塞时CPU可能会处于空闲状态。这将造成大量的计算资源的浪费。而在程序中使用多线程可以在某一个线程处于休眠或阻塞时,而CPU又恰好处于空闲状态时来运行其他的线程。这样CPU就很难有空闲的时候。因此,CPU资源就得到了充分地利用。
2. 简化编程模型
如果程序只完成一项任务,那只要写一个单线程的程序,并且按着执行这个任务的步骤编写代码即可。但要完成多项任务,如果还使用单线程的话,那就得在在程序中判断每项任务是否应该执行以及什么时候执行。如显示一个时钟的时、分、秒三个指针。使用单线程就得在循环中逐一判断这三个指针的转动时间和角度。如果使用三个线程分另来处理这三个指针的显示,那么对于每个线程来说就是指行一个单独的任务。这样有助于开发人员对程序的理解和维护。
3. 简化异步事件的处理
当一个服务器应用程序在接收不同的客户端连接时最简单地处理方法就是为每一个客户端连接建立一个线程。然后监听线程仍然负责监听来自客户端的请求。如果这种应用程序采用单线程来处理,当监听线程接收到一个客户端请求后,开始读取客户端发来的数据,在读完数据后,read方法处于阻塞状态,也就是说,这个线程将无法再监听客户端请求了。而要想在单线程中处理多个客户端请求,就必须使用非阻塞的Socket连接和异步I/O.但使用异步I/O方式比使用同步I/O更难以控制,也更容易出错。因此,使用多线程和同步I/O可以更容易地处理类似于多请求的异步事件。
4. 使GUI更有效率
使用单线程来处理GUI事件时,必须使用循环来对随时可能发生的GUI事件进行扫描,在循环内部除了扫描GUI事件外,还得来执行其他的程序代码。如果这些代码太长,那么GUI事件就会被“冻结”,直到这些代码被执行完为止。
在现代的GUI框架(如SWING、AWT和SWT)中都使用了一个单独的事件分派线程(event dispatch thread,EDT)来对GUI事件进行扫描。当我们按下一个按钮时,按钮的单击事件函数会在这个事件分派线程中被调用。由于EDT的任务只是对GUI事件进行扫描,因此,这种方式对事件的反映是非常快的。
5. 节约成本
提高程序的执行效率一般有三种方法:
(1)增加计算机的CPU个数。
(2)为一个程序启动多个进程
(3)在程序中使用多进程。
第一种方法是最容易做到的,但同时也是最昂贵的。这种方法不需要修改程序,从理论上说,任何程序都可以使用这种方法来提高执行效率。第二种方法虽然不用购买新的硬件,但这种方式不容易共享数据,如果这个程序要完成的任务需要必须要共享数据的话,这种方式就不太方便,而且启动多个线程会消耗大量的系统资源。第三种方法恰好弥补了第一种方法的缺点,而又继承了它们的优点。也就是说,既不需要购买CPU,也不会因为启太多的线程而占用大量的系统资源(在默认情况下,一个线程所占的内存空间要远比一个进程所占的内存空间小得多),并且多线程可以模拟多块CPU的运行方式,因此,使用多线程是提高程序执行效率的最廉价的方式。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。关于java多线程的问题,请各位大虾指点!!!
[问题点数:0分]
关于java多线程的问题,请各位大虾指点!!!
[问题点数:0分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2001年5月 Java大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。您所在的位置: &
Java多线程编程实战精要(1)
Java多线程编程实战精要(1)
多线程在目前的应用开发中被广泛使用;本文向您介绍Java多线程编程的原理和具体实现,通过简单的编程示例来说明 Java 程序中的多线程是多么直观。
在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为Java 编程语言提供了语言级的支持。本文通过简单的编程示例来说明Java多线程编程多么直观。读完本文以后,用户应该能够编写简单的多线程程序。
51CTO编辑推荐:
为什么会排队等待?
下面的这个简单的 Java 程序完成四项不相关的任务。这样的程序有单个控制线程,控制在这四个任务之间线性地移动。此外,因为所需的资源 ? 打印机、磁盘、数据库和显示屏 -- 由于硬件和软件的限制都有内在的潜伏时间,所以每项任务都包含明显的等待时间。因此,程序在访问数据库之前必须等待打印机完成打印文件的任务,等等。如果您正在等待程序的完成,则这是对计算资源和您的时间的一种拙劣使用。改进此程序的一种方法是使它成为多线程的。
四项不相关的任务&&&&class&myclass&{& &static&public&void&main(String&args[])&{& &print_a_file();& &manipulate_another_file();& &access_database();& &draw_picture_on_screen();& &}& &}&
在本例中,每项任务在开始之前必须等待前一项任务完成,即使所涉及的任务毫不相关也是这样。但是,在现实生活中,我们经常使用多线程模型。我们在处理某些任务的同时也可以让孩子、配偶和父母完成别的任务。例如,我在写信的同时可能打发我的儿子去邮局买邮票。用软件术语来说,这称为多个控制(或执行)线程。
可以用两种不同的方法来获得多个控制线程:
在大多数操作系统中都可以创建多个进程。当一个程序启动时,它可以为即将开始的每项任务创建一个进程,并允许它们同时运行。当一个程序因等待网络访问或用户输入而被阻塞时,另一个程序还可以运行,这样就增加了资源利用率。但是,按照这种方式创建每个进程要付出一定的代价:设置一个进程要占用相当一部分处理器时间和内存资源。而且,大多数操作系统不允许进程访问其他进程的内存空间。因此,进程间的通信很不方便,并且也不会将它自己提供给容易的编程模型。
线程也称为轻型进程 (LWP)。因为线程只能在单个进程的作用域内活动,所以创建线程比创建进程要廉价得多。这样,因为线程允许协作和数据交换,并且在计算资源方面非常廉价,所以线程比进程更可取。线程需要操作系统的支持,因此不是所有的机器都提供线程。Java 编程语言,作为相当新的一种语言,已将Java多线程编程支持与语言本身合为一体,这样就对线程提供了强健的支持。
使用Java 编程语言实现线程
Java编程语言使多线程如此简单有效,以致于某些程序员说它实际上是自然的。尽管在 Java 中使用线程比在其他语言中要容易得多,仍然有一些概念需要掌握。要记住的一件重要的事情是 main() 函数也是一个线程,并可用来做有用的工作。程序员只有在需要多个线程时才需要创建新的线程。
Thread 类是一个具体的类,即不是抽象类,该类封装了线程的行为。要创建一个线程,程序员必须创建一个从 Thread 类导出的新类。程序员必须覆盖 Thread 的 run() 函数来完成有用的工作。用户并不直接调用此函数;而是必须调用 Thread 的 start() 函数,该函数再调用 run()。下面的代码说明了它的用法:
创建两个新线程&&&&&import&java.util.*;& &class&TimePrinter&extends&Thread&{& &int&pauseT& &String&& &public&TimePrinter(int&x,&String&n)&{& &pauseTime&=&x;& &name&=&n;& &}& &public&void&run()&{& &while(true)&{& &try&{& &System.out.println(name&+&":"&+&new& &Date(System.currentTimeMillis()));& &Thread.sleep(pauseTime);& &}&catch(Exception&e)&{& &System.out.println(e);& &}& &}& &}& &static&public&void&main(String&args[])&{& &TimePrinter&tp1&=&new&TimePrinter(1000,&"Fast&Guy");& &tp1.start();& &TimePrinter&tp2&=&new&TimePrinter(3000,&"Slow&Guy");& &tp2.start();& &}& &}&
在本例中,我们可以看到一个简单的程序,它按两个不同的时间间隔(1 秒和 3 秒)在屏幕上显示当前时间。这是通过创建两个新线程来完成的,包括 main() 共三个线程。但是,因为有时要作为线程运行的类可能已经是某个类层次的一部分,所以就不能再按这种机制创建线程。虽然在同一个类中可以实现任意数量的接口,但 Java 编程语言只允许一个类有一个父类。同时,某些程序员避免从 Thread 类导出,因为它强加了类层次。对于这种情况,就要 runnable 接口。
Runnable 接口
此接口只有一个函数,run(),此函数必须由实现了此接口的类实现。但是,就运行这个类而论,其语义与前一个示例稍有不同。我们可以用 runnable 接口改写前一个示例。(不同的部分用黑体表示。)
创建两个新线程而不强加类层次 &&&import&java.util.*;& &class&TimePrinter&implements&Runnable&{& &int&pauseT& &String&& &public&TimePrinter(int&x,&String&n)&{& &pauseTime&=&x;& &name&=&n;& &}& &public&void&run()&{& &while(true)&{& &try&{& &System.out.println(name&+&":"&+&new& &Date(System.currentTimeMillis()));& &Thread.sleep(pauseTime);& &}&catch(Exception&e)&{& &System.out.println(e);& &}& &}& &}& &static&public&void&main(String&args[])&{& &Thread&t1&=&new&Thread(new&TimePrinter(1000,&"Fast&Guy"));& &t1.start();& &Thread&t2&=&new&Thread(new&TimePrinter(3000,&"Slow&Guy"));& &t2.start();& &}& &}&
请注意,当使用 runnable 接口时,您不能直接创建所需类的对象并运行它;必须从 Thread 类的一个实例内部运行它。许多程序员更喜欢 runnable 接口,因为Java多线程编程从 Thread 类继承会强加类层次。
内容导航&第 1 页: &第 2 页:
关于的更多文章
Angular.js 是一个MV*(Model-View-Whatever,不管是MVC或者MVVM
魅族应用商店作为国内最早的应用分发平台,国内首创了许多新业务模式
Eclipse 是一个开源的、可扩展的集成开发环境。平台本
这个架构是从我近期在做的一个项目中剥离出来的,这个
MongoDB的转变也正是10gen的转变,Dwight Merriman在
本书全面翔实地介绍了各种病毒的原理,以操作系统的发展为主线,结合病毒的发展过程来综合分析病毒。在分析工具上,较多地利用了
51CTO旗下网站java多线程_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
java多线程
上传于||文档简介
&&j​a​v​a​多​线​程
大小:767.00KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢}

我要回帖

更多关于 深入理解java多线程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信