您的位置:首页 > 编程语言 > Java开发

线程进程【重磅出击】 java入门到精通——多线程(上)

2013-04-21 20:54 519 查看
本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~

Java 多线程(上)

1 线程和进程的别区

1.1进程和线程

进程是指一个内存中行运的应用程序,每一个进程都有自己立独的一块内存空间,一个进程中可以有多个线程。比如在Windows统系中,一个行运的xx.exe就是一个进程。Java程序的进程里有几个线程:主线程, 垃圾回收线程(后台线程)。

线程是指进程中的一个执行务任(制控单元),一个进程中可以行运多个线程,多个线程可享共数据。多进程:操作统系中同时行运的多个程序,在一同个进程中同时行运的多个务任;一个进程最少有一个线程,为了高提效率,可以在一个进程中开启多个制控单元。

并发行运。如:多线程下载软件。

多线程下载:此时线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开起好几个下载通道.当服务器供提下载服务时,用使下载者是享共带宽的,在优先级同相的情况下,总服务器会对总下载线程停止平均分配。不难理解,如果你线程多的话,那下载的越快。现行流的下载软件都支撑多线程。可以成完同时行运,但是通过程序行运的结果现发,虽然同时行运,但是每一次结果都不分歧。

因为多线程存在一个性特:随机性。

形成的因原:CPU在间瞬一直切换去理处各个线程而致使的。

可以理解成多个线程在抢cpu源资。

1.2 线程与进程的比拟

线程有具多许传统进程所有具的征特,故又称为轻型进程或进程元;而把传统的进程称为重型进程,它相当于只有一个线程的务任。在引入了线程的操作统系中,常通一个进程都有若干个线程,最少要需一个线程。

进程与线程的别区:

1.进程有立独的进程空间,进程中的数据放存空间(堆空间和栈空间)是立独的。

2.线程的堆空间是享共的,栈空间是立独的,线程耗消的源资也比进程小,相互之间可以影响的。

如果想细详懂得线程与进程请看我的线程与进程的细详分析

2. 创立线程

2.1 创立线程第一种法方(继承):

1. 新建一个类,继承Thread

2. 复写 run法方

3. 创立一个线程对象

4. 启动线程(线程对象.start())

代码如下:

class MyThread extends Thread{
public void run() {

for (int i = 0; i < 100; i++) {
System.out.println("MyThread---->"+ i);
}
}
}
class ThreadDemo1 {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println("main------>" +i);
if(i == 10){
new MyThread().start();
}
}
}
}


2.2 创立线程第二种法方(实现):

实现Runnable接口
1. 子类覆盖接口中的run法方。
2. 通过Thread类创立线程,并将实现了Runnable接口的子类对象作为参数递传给Thread类的构造函数。
3. Thread类对象调用start法方开启线程。


代码如下:

class MyThread2 implements Runnable {
public void run() {
// 线程体
for (int i = 0; i < 100; i++) {
System.out.println("MyThread2----->" + i);
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println("main-->" +i);
if (i == 10) {
new Thread(new MyThread2()).start();
}
}
}
}

在现我们通过一个经典案例来说明这两种法方的别区:

售票的例子,这个例子基本上每一本java入门书上会都有!

需求:有50张票要需3个售票口窗卖出;用两种开启线程法方买票,视察两种法方买票的结果有什么不同?

1. 继承Thread法方

class Ticket1 extends Thread{
int num = 20;
public Ticket1(String name){
super(name);
}
public void run() {
for (int i = 0; i < 100; i++) {
if(num >0) {
System.out.println(getName()+"卖出第" +num-- +"张");
}
}
}
}
public class TicketDemo {
public static void main(String[] args) {
//3个口窗买
new Ticket1("售票员-1").start();
new Ticket1("售票员-2").start();
new Ticket1("售票员-3").start();
}
  }


输出结果的一部分:


售票员-1卖出第50张

售票员-3卖出第50张

售票员-2卖出第50张

售票员-3卖出第49张

售票员-1卖出第49张

售票员-3卖出第48张

售票员-3卖出第47张

每日一道理

“一年之计在于春”,十几岁的年纪,正是人生的春天,别辜负了岁月老人的厚爱与恩赐。行动起来,播种梦想吧!





2. 实现Runnable法方

class Ticket2 extends Object implements Runnable{
int num = 20;
public void run() {
for (int i = 0; i < 50; i++) {
if(num >0) {
System.out.println(Thread.currentThread().getName()+"卖出第" +num-- +"张");

}
}
}
}
public class TicketDemo2 {
public static void main(String[] args) {
Runnable target = new Ticket2();
new Thread(target,"售票员-1").start();
new Thread(target,"售票员-2").start();
new Thread(target,"售票员-3").start();
}
}


输出结果的一部分:

售票员-1卖出第50张

售票员-3卖出第48张

售票员-2卖出第49张

售票员-3卖出第46张

售票员-2卖出第45张

售票员-2卖出第43张

currentThread():回返对以后正在执行的线程对象的引用。

getName():获得线程名称。

setName()置设线程名字。

将两种法方的输出结果停止比拟,我们会现发

继承Thread类的输出结果一共印打了150条,说明一条票被卖了三次,这显然是不正确的。

而实现Runnable接口却没有现出这样的问题。

解释:

因为一个线程只能启动一次,通过Thread实现线程时,线程和线程所要执行的务任是绑捆在一起的。也就使得一个务任只能启动一个线程,不同的线程执行的务任是不同相的,所以没有必要,也不能让两个线程享共彼此务任中的源资。

一个务任可以启动多个线程,通过Runnable法方实现的线程,际实是辟开一个线程,将务任递传进去,由此线程执行。可以实例化多个 Thread对象,将一同务任递传进去,也就是一个务任可以启动多个线程来执行它。这些线程执行的是一同个务任,所以他们的源资是享共。

两种不同的线程实现法方本身就决议了其是不是能停止源资享共

继承Thread

同份源资不享共并且由于java的单继承,程序以后不便于扩展。

实现Runnable:(推荐)

多个线程享共一个标目源资,合适多线程理处一同份源资。

该类还可以继承其他类,也可以实现其他接口。

3 线程的生命周期



3.1 线程的生命周期之新建和就绪态状

新建:当程序用使new创立一个线程后,该线程处于新建态状,此时他和其他java对象一样,仅仅由Java虚拟机为其分配内存并初始化成员变量值。【 Thread r = new Thread() 】

就绪:当线程对象调用start()法方后,该线程处于就绪态状,线程计入线程队列队排,此时该态状线程并未开始执行,它仅表现可以行运了。至于该线程何时行运,取决于JVM线程调度器的调度。【 r.start() 】

3.2 线程的生命周期之行运和阻塞态状

行运:若处于就绪态状的线程取得了CPU,开始执行run()线程执行体,该线程处于执行态状。

阻塞:线程行运中程过要需被中断,的目是是其他的线程取得执行的机遇。该态状就会进入阻塞态状。

注意:阻塞态状不能直接转成行运态状,阻塞态状只能新重进入就绪态状。

3.3 线程的生命周期之殒命

run()执行成完,线程畸形束结; 线程抛出未获捕的Exception或Error;

调用线程的stop()。(易致使死锁,不推荐)

注意:

主线程束结后,其他线程不受其影响,不会随之束结;

一旦子线程启动起来后,就具有和主线程相称位置,不受主线程影响。

试测线程是不是在世,可用线程对象的isAlive()法方。当线程处于就绪,行运,阻塞态状回返true。当线程处于新建和殒命态状,回返false。

已殒命的线程是不可以通过start()法方唤醒线程的,否则发引IllegalThreadStateException常异;

楼猪不是什么牛大,但自我评价认为还总结的不错,挺合适新手。 如果现发哪里错了,望各位牛大点指!

文章结束给大家分享下程序员的一些笑话语录:

那是习惯决定的,一直保持一个习惯是不好的!IE6的用户不习惯多标签,但是最终肯定还是得转到多标签的浏览器。历史(软件UI)的进步(改善)不是以个人意志(习惯)为转移的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: