`
yesjavame
  • 浏览: 656397 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

多线程编程 基础篇 (二)

阅读更多

基础篇(二)

在进入java平台的线程对象之前,基于基础知识(一)的一些问题,我先插入两个基本概念.

[线程的并发与并行]

在单CPU系统中,系统调度在某一时刻只能让一个线程运行,虽然这种调试机制有多种形式
(大多数是时间片轮巡为主),但无论如何,要通过不断切换需要运行的线程让其运行的方式
就叫并发(concurrent).

而在多CPU系统中,可以让两个以上的线程同时运行,这种可以同时让两个以上线程同时运行
的方式叫做并行(parallel).

在上面包括以后的所有论述中,请各位朋友谅解,我无法用最准确的词语来定义储如并发和
并行这类术语,但我以我的经验能通俗地告诉大家它是怎么一回事,如果您看到我说的一些
"标准"文档上说的不一样,只要意思一致,那您就不要挑刺了.

[JAVA线程对象]

现在我们来开始考察JAVA中线程对象.
在JAVA中,要开始一个线程,有两种方式.一是直接调用Thread实例的start()方法,二是
将Runable实例传给一个Thread实例然后调用它的start()方法.

在基础知识(一)中已经说过,线程对象和线程是两个完全不同的概念.这里我们再次
深入一下,生成一个线程的实例,并不代表启动了线程.而启动线程是说在某个线程对象上启动
了该实例对应的线程,当该线程结束后,并不会就立即消失.

对于从很多书籍上可以看到的基础知识我就不用多说了.既然是基础知识,我也着重
于从普通文档上读不到的内容.
所以本节我重点要说的是两种线程对象产生线程方式的区别.


classMyThreadextendsThread{
publicintx=0;

publicvoidrun(){

for(inti=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exceptione){}
System.out.println(x++);

}
}
}

如果我们生成MyThread的一个实例,然后调用它的start();方法,那么就产生了这个实例对应
的线程:

publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
MyThreadmt=newMyThread();
mt.start();
}
}


不用说,最终会打印出0到99,现在我们稍微玩一点花样:

publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
MyThreadmt=newMyThread();
mt.start();
System.out.println(101);
}
}

也不用说,在基础知识(一)中我们知道由于单CPU的原因,一般会先打印101,然后打印
0到99.不过我们可以控制线程让它按我们的意思来运行:

publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
MyThreadmt=newMyThread();
mt.start();
mt.join();
System.out.println(101);
}
}

好了,我们终于看到,mt实例对应的线程(假如我有时说mt线程请你不要怪我,不过我尽量不这么说)
在运行完成后,主线程才打印101.因为我们让主当前线程(这里是主线程)等待mt线程的运行结束.
"在线程对象a上调用join()方法,就是让当前正在执行的线程等待线程对象a对应的线程运行完成后
才继续运行."请大家一定要深刻理解并熟记这句话,而我这里引出这个知识点的目的是为了让你继
续看下面的例子:



publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
MyThreadmt=newMyThread();
mt.start();
mt.join();
Thread.sleep(3000);
mt.start();
}
}

当线程对象mt运行完成后,我们让主线程休息一下,然后我们再次在这个线程对象上启动线程.结果我
们看到:

Exceptioninthread"main"java.lang.IllegalThreadStateException

也就是这种线程对象一时运行一次完成后,它就再也不能运行第二次了.
我们可以看一下它有具体实现:
publicsynchronizedvoidstart(){
if(started)
thrownewIllegalThreadStateException();
started=true;
group.add(this);
start0();
}

一个Thread的实例一旦调用start()方法,这个实例的started标记就标记为true,事实中不管这个线程
后来有没有执行到底,只要调用了一次start()就再也没有机会运行了,这意味着:

[通过Thread实例的start(),一个Thread的实例只能产生一个线程]

那么如果要在一个实例上产生多个线程(多个线程共同访问同一实例的一些共同资源),我们应该如何做呢?这就是Runnable
接口给我们带来的伟大的功能.

classRimplementsRunnable{
privateintx=0;
publicvoidrun(){

for(inti=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exceptione){}
System.out.println(x++);

}
}
}


正如它的名字一样,Runnable的实例是可运行的,但它自己并不能直接运行,它需要被Thread对象来
包装才行运行:

publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
newThread(newR()).start();
}
}

当然这个结果和mt.start()没有什么区别.但如果我们把一个Runnable实例给Thread对象多次包装,我
们就可以看到它们实际是在同一实例上启动线程:

publicclassTest{
publicstaticvoidmain(String[]args)throwsException{
Rr=newR();
for(inti=0;i<10;i++)
newThread(r).start();
}
}

x是实例对象,但结果是x被加到了999,说明这10个线程是在同一个r对象上运行的.请大家注意,因为这个
例子是在单CPU上运行的,所以没有对多个线程同时操作共同的对象进行同步.这里是为了说明的方便而
简化了同步,而真正的环境中你无法预知程序会在什么环境下运行,所以一定要考虑同步.


到这里我们做一个完整的例子来说明线程产生的方式不同而生成的线程的区别:

packagedebug;

importjava.io.*;
importjava.lang.Thread;


classMyThreadextendsThread{
publicintx=0;

publicvoidrun(){
System.out.println(++x);
}
}

classRimplementsRunnable{
privateintx=0;
publicvoidrun(){
System.out.println(++x);
}
}

publicclassTest{
publicstaticvoidmain(String[]args)throwsException{

for(inti=0;i<10;i++){
Threadt=newMyThread();
t.start();
}
Thread.sleep(10000);//让上面的线程运行完成
Rr=newR();
for(inti=0;i<10;i++){
Threadt=newThread(r);
t.start();
}
}
}

上面10个线程对象产生的10个线程运行时打印了10次1.
下面10个线程对象产生的10个线程运行时打印了1到10.

我们把下面的10个线程称为同一实例(Runnable实例)的多个线程.

下节我们将研究线程对象方法,还是那句话,一般文档中可以读到的内容我不会介绍太多
请大家自己了解.

分享到:
评论

相关推荐

    java多线程编程实战指南 核心篇 代码

    随着现代处理器的生产工艺从提升...《Java多线程编程实战指南(核心篇)》适合有一定Java语言基础的读者作为入门多线程编程之用,也适合有一定多线程编程经验的读者作为重新梳理知识结构以提升认知层次和参考之用。

    多线程编程实战指南-核心篇

    java多线程编程指南核心篇,各人觉得并发编程的艺术看起来更枯燥,还是实战带感,当然,有基础的话更容易些

    Java多线程编程实战指南-设计模式篇

    随着CPU 多核时代的到来,多线程编程在充分利用计算资源、提高软件服务质量方面扮演了越来越重要的角色。...《Java多线程编程实战指南(设计模式篇)》适合有一定Java 多线程编程基础、经验的读者。

    .NET多线程编程(1):多任务和多线程

    首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述。NET平台上多线程编程的知识,诸如System.Threading命名空间的重要类以及方法,并就一些例子程序来作...

    .net 线程详解 基础篇

    WinForm多线程编程篇 * 我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决? * Invoke,BeginInvoke干什么用的,内部是怎么实现的 * 每个线程都有消息队列吗? * 为什么Winform不允许跨线程...

    Java多线程之基础篇(一).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    Java多线程之基础篇(二).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    . NET C#多线程编程专门教程

    首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述.NET平台上多线程编程的知识,诸如System.Threading命名空间的重要类以及方法,并就一些例子程序来作说明...

    .Net 多线程详解

    WinForm多线程编程篇 • 我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决? • Invoke,BeginInvoke干什么用的,内部是怎么实现的 • 每个线程都有消息队列吗? • 为什么Winform不允许跨...

    java_多线程开发

    java_多线程开发 分为: 多线程编程——基础篇 多线程编程——实战篇

    深入浅出Win32多线程程序设计[收集].pdf

    深入浅出Win32多线程程序设计[收集].pdf

    C#网络编程高级篇之网页游戏辅助程序设计

    《c#网络编程高级篇之网页游戏辅助程序设计》涉及的领域包括多线程编程技术、socket套接字编程、tcp协议编程、http协议编程、远程控制技术、木马技术、模拟键盘和鼠标技术、网页游戏辅助程序设计技术等。...

    权威.NET多线程详解(源码示例)

    WinForm多线程编程篇 • 我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决? • Invoke,BeginInvoke干什么用的,内部是怎么实现的 • 每个线程都有消息队列吗? • 为什么Winform不允许跨...

    python 零基础学习篇多任务编程线程2 多线程的使用 .mp4

    python 零基础学习篇

    老王Python基础+进阶+项目篇(高清无密)

    进阶篇28-高性能的多线程网络资源访问第二节 进阶篇29-http相关讲解 进阶篇30-wsgi讲解 进阶篇31-进阶综合习题应用 进阶篇32-综合习题讲解 进阶篇33-进阶项目讲解第二节 进阶篇34-项目讲解第三节 老王Python教程 ...

    Java实验6多线程.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)...进阶篇有反射、泛型、注解、网络编程、多线程、序列化、数据库、Servlet、JSP、XML解析、单例模式与枚举。本专栏主要为Java入门者提供实验参考。

    c# 多线程编程 入门篇

    多线程应该是编程工作者的基础技能, 但这个基础对我来讲的确有点难(起码昨天以前是这样).

    读书笔记-Java并发编程实战-基础篇

    读书笔记-Java并发编程实战-基础篇

    《Java语言程序设计——基础篇》第三章选择作业答案.zip

    中文版分为《Java语言程序设计基础篇》和《Java语言程序设计进阶篇》主要介绍语法结构、面向对象程序设计基础知识到面向对象程序设计、图形用户界面设计、异常处理、二进制I/O和递归等内容。进阶篇主要介绍数据结构...

    C++编程基础知识概述

    C++是一种强大且广泛使用的编程语言,用于开发各种应用程序,从系统级应用到图形用户界面。...如果您想更深入地学习C++,可以探索面向对象编程、模板编程、多线程编程等更高级主题,以充分利用这门强大的编程语言。

Global site tag (gtag.js) - Google Analytics