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

本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~

    

Java 多线程(上)

    

线程和进程的别区

    

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.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)的进步(改善)不是以个人意志(习惯)为转移的!

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3034446.html