本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~
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)的进步(改善)不是以个人意志(习惯)为转移的!