• 线程进程【重磅出击】 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)的进步(改善)不是以个人意志(习惯)为转移的!

  • 相关阅读:
    第二次作业
    第五次作业
    第四次作业
    第三次作业
    第二次作业
    第三次作业
    第二次作业
    第二次作业
    gravity
    card
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3034446.html
Copyright © 2020-2023  润新知