在进入java平台的线程对象之前,基于基础知识(一)的一些问题,我先插入两个基本概念.
[线程的并发与并行]
在单CPU系统中,系统调度在某一时刻只能让一个线程运行,虽然这种调试机制有多种形式
(大多数是时间片轮巡为主),但无论如何,要通过不断切换需要运行的线程让其运行的方式
就叫并发(concurrent).
而在多CPU系统中,可以让两个以上的线程同时运行,这种可以同时让两个以上线程同时运行
的方式叫做并行(parallel).
在上面包括以后的所有论述中,请各位朋友谅解,我无法用最准确的词语来定义储如并发和
并行这类术语,但我以我的经验能通俗地告诉大家它是怎么一回事,如果您看到我说的一些
"标准"文档上说的不一样,只要意思一致,那您就不要挑刺了.
[JAVA线程对象]
现在我们来开始考察JAVA中线程对象.
在JAVA中,要开始一个线程,有两种方式.一是直接调用Thread实例的start()方法,二是
将Runable实例传给一个Thread实例然后调用它的start()方法.
在基础知识(一)中已经说过,线程对象和线程是两个完全不同的概念.这里我们再次
深入一下,生成一个线程的实例,并不代表启动了线程.而启动线程是说在某个线程对象上启动
了该实例对应的线程,当该线程结束后,并不会就立即消失.
对于从很多书籍上可以看到的基础知识我就不用多说了.既然是基础知识,我也着重
于从普通文档上读不到的内容.
所以本节我重点要说的是两种线程对象产生线程方式的区别.
class MyThread extends Thread{
public int x = 0;
public void run(){
for(int i=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(x++);
}
}
}
如果我们生成MyThread的一个实例,然后调用它的start();方法,那么就产生了这个实例对应
的线程:
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
}
}
不用说,最终会打印出0到99,现在我们稍微玩一点花样:
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
System.out.println(101);
}
}
也不用说,在基础知识(一)中我们知道由于单CPU的原因,一般会先打印101,然后打印
0到99.不过我们可以控制线程让它按我们的意思来运行:
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
mt.join();
System.out.println(101);
}
}
好了,我们终于看到,mt实例对应的线程(假如我有时说mt线程请你不要怪我,不过我尽量不这么说)
在运行完成后,主线程才打印101.因为我们让主当前线程(这里是主线程)等待mt线程的运行结束.
"在线程对象a上调用join()方法,就是让当前正在执行的线程等待线程对象a对应的线程运行完成后才继续运行." 请大家一定要深刻理解并熟记这句话,而我这里引出这个知识点的目的是为了让你继
续看下面的例子:
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
mt.join();
Thread.sleep(3000);
mt.start();
}
}
当线程对象mt运行完成后,我们让主线程休息一下,然后我们再次在这个线程对象上启动线程.结果我们看到:
Exception in thread "main" java.lang.IllegalThreadStateException
也就是这种线程对象一时运行一次完成后,它就再也不能运行第二次了.
我们可以看一下它有具体实现:
public synchronized void start() {
if (started)
throw new IllegalThreadStateException();
started = true;
group.add(this);
start0();
}
一个Thread的实例一旦调用start()方法,这个实例的started标记就标记为true,事实中不管这个线程后来有没有执行到底,只要调用了一次start()就再也没有机会运行了,这意味着:
通过Thread实例的start(),一个Thread的实例只能产生一个线程
那么
如果要在一个实例上产生多个线程(也就是我们常说的
线程池),我们应该如何做呢?这就是
Runnable接口给我们带来的伟大的功能.
class R implements Runnable{
private int x = 0;
public void run(){
for(int i=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(x++);
}
}
}
正如它的名字一样,Runnable的实例是可运行的,但它自己并不能直接运行,它需要被Thread对象来包装才行运行:
public class Test {
public static void main(String[] args) throws Exception{
new Thread(new R()).start();
}
}
当然这个结果和mt.start()没有什么区别.但如果我们把一个Runnable实例给Thread对象多次包装,我们就可以看到它们实际是在同一实例上启动线程:
public class Test {
public static void main(String[] args) throws Exception{
R r = new R();
for(int i=0;i<10;i++)
new Thread(r).start();
}
}
x是实例对象,但结果是x被加到了999,说明这10个线程是在同一个r对象上运行的.请大家注意,因为这个例子是在单CPU上运行的,所以没有对多个线程同时操作共同的对象进行同步.这里是为了说明的方便而简化了同步,而真正的环境中你无法预知程序会在什么环境下运行,所以一定要考虑同步.
到这里我们做一个完整的例子来说明线程产生的方式不同而生成的线程的区别:
package debug;
import java.io.*;
import java.lang.Thread;
class MyThread extends Thread{
public int x = 0;
public void run(){
System.out.println(++x);
}
}
class R implements Runnable{
private int x = 0;
public void run(){
System.out.println(++x);
}
}
public class Test {
public static void main(String[] args) throws Exception{
for(int i=0;i<10;i++){
Thread t = new MyThread();
t.start();
}
Thread.sleep(10000);//让上面的线程运行完成
R r = new R();
for(int i=0;i<10;i++){
Thread t = new Thread(r);
t.start();
}
}
}
上面10个线程对象产生的10个线程运行时打印了10次1.
下面10个线程对象产生的10个线程运行时打印了1到10.
我们把下面的10个线程称为同一实例(Runnable实例)的多个线程.
分享到:
相关推荐
《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...
《多线程编程实战指南-核心篇》是针对Java开发者深入理解并掌握多线程编程的一本实战性书籍。在当今的并发计算环境中,多线程技术是必不可少的知识点,它能够有效地利用多核处理器资源,提高程序的执行效率。本书以...
随着现代处理器的生产工艺从提升...《Java多线程编程实战指南(核心篇)》适合有一定Java语言基础的读者作为入门多线程编程之用,也适合有一定多线程编程经验的读者作为重新梳理知识结构以提升认知层次和参考之用。
在Java编程中,多线程是一项关键技能,它允许程序同时执行多个任务,极大地提高了程序的...通过阅读"Java多线程编程实战指南 设计模式篇.pdf",你将获得更深入的理论知识和实践技巧,为你的编程事业奠定坚实的基础。
在VC++环境中,多线程编程是开发高效应用程序的关键技术之一。它允许程序同时执行多个任务,提升系统资源利用率,特别是在处理I/O密集型或计算密集型任务时。本篇文章将详细阐述VC++中实现多线程的三种常见方法:...
总之,Java多线程基础篇讲解涵盖了多线程编程的基本原理和实践,通过学习这些内容,开发者可以掌握如何在Java环境中创建和管理线程,以及如何优化多线程程序以充分利用系统资源,从而编写出高效的并发应用程序。
《Java多线程编程实战指南》是一本深入探讨Java并发编程的书籍,涵盖了核心篇与设计模式篇。这本书旨在帮助开发者理解和掌握Java平台上的多线程编程,提升系统性能和可扩展性。在Java世界中,多线程是实现并发处理、...
本资源“Java多线程编程实战指南+设计模式篇”深入探讨了这两个主题,旨在帮助开发者提升其在并发编程和软件设计上的技能。 **一、Java多线程** 1. **线程基础**:Java中的线程是程序执行的最小单位。Java通过`...
总结来说,《Windows多线程编程及例程》这篇教程是学习Windows环境下多线程开发的宝贵资料,通过理论讲解和实战演练,能够帮助开发者建立起扎实的多线程编程基础,提升软件设计和性能优化的能力。遗憾的是,缺少第四...
随着CPU 多核时代的到来,多线程编程在充分利用计算资源、提高软件服务质量方面扮演了越来越重要的角色。...《Java多线程编程实战指南(设计模式篇)》适合有一定Java 多线程编程基础、经验的读者。
二、多线程技术 1. **线程的概念**:线程是操作系统资源调度的基本单位,一个进程中可以包含多个线程,它们共享进程资源,独立执行任务。 2. **线程的优点**:多线程可以提高程序的执行效率,特别是在I/O密集型任务...
.NET线程详解基础篇主要涉及了线程的创建、类型、异步操作、WinForm多线程编程、线程池以及同步策略等多个方面。以下是对这些知识点的详细说明: 1. **怎样创建一个线程**: - 使用`Thread`类:通过创建`Thread`...
本篇内容将基于《MFC多线程编程.pdf》的部分内容,详细介绍多线程的概念、Win32 API对多线程的支持以及MFC框架下的多线程编程技巧。 #### 二、多线程基础理论 ##### 2.1 问题提出 以一个简单的例子开始——一个名为...
学习"JAVA程序员必读基础篇"的内容,将帮助初学者建立起坚实的Java编程基础,为进一步深入学习Java高级特性,如Spring框架、JDBC数据库访问、多线程编程等打下坚实的基础。通过实践和不断练习,你将能够熟练掌握这个...
在本篇文章中,我们将深入探讨如何使用Qtcreator进行多线程编程,以及如何实现每秒输出一个内容的功能。 首先,我们要理解多线程的概念。在单线程环境中,程序执行是顺序的,一次只能处理一个任务。而多线程则允许...
在IT领域,多线程编程是一项关键技能,尤其是在开发高效、响应迅速的应用程序时。MFC(Microsoft Foundation Classes)是微软提供的一种C++类库,它简化了Windows应用程序的开发,包括多线程的支持。本篇文章将深入...
4. **第九章多线程编程**: 这个章节可能详细介绍了如何在MFC中设计和管理多线程,包括线程的生命周期管理、异常处理、线程同步策略、线程间通信以及多线程环境下Socket编程的实践案例。 综上所述,MFC多线程...
在本篇论文“Linux下多线程编程的聊天软件”中,作者李杨探讨了如何利用Linux操作系统和多线程编程技术开发一款功能完备的网络聊天软件。在信息时代的背景下,网络聊天工具已经成为日常生活中不可或缺的通讯手段,而...