现在的位置: 首页 > 综合 > 正文

黑马程序员_<<线程,Thread>>

2018年02月17日 ⁄ 综合 ⁄ 共 4335字 ⁄ 字号 评论关闭

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流!
--------------------

1.进程


       1.概述:

              进程就是正在执行的一个程序。可以说是静态的,当进程一旦执行,那么就会在内存中给其分配一定的内存空间,供其运行。

      2.从系统上来理解:进程有单进程和多进程

           2-1.单进程:就是只能运行一个程序,只有这个程序运行完了,才能运行其他的进程,例如:DOS系统,他的特点就是只要是一种病毒,就会死机,原因就是采用的是单进程

           2-2.多进程:就是可以同时运行多个程序,例如现在的Window系统,采用的就是多进程

           2-3.Java虚拟机把其封装成了对象,供其使用。

           2-4.进程和线程的之间的举例说明:打开qq程序,qq就是一个进程,那么线程就是其中的qq连天窗口。

2. 线程的概述

         1.概述:线程是动态的,是进程中的控制单元,一个进程中可以执行多个线程,线程控制着进程。

         2.一个进程中至少存在一个线程在执行,

             例如:java虚拟机启动后,不只是存在的一个线程,一个是主线程,一个是垃圾回收的线程。

         3.线程的执行必须是在有进程的基础之上,当一个线程消失了,那么进程不一定会消失,但是进程消失了,那么线程肯定会消失。

         4.主线程:在系统中就是进程一旦创建,就是创建一个线程,那么就是个主线程,那么再有其他的线程生成的话,那就是其子类,在java虚拟机中的主线程是在运行主函数的线程。

          5.多线程:多线程会提高执行速度(这只是多线程其中的一个功能例如:下载)当是多线程的话,那么各个线程之间会有优先级。当线程抢到了CPU,谁就会执行。

3.  线程的创建方法

        3-1.继承Thread类。

            1.定义类继承Thread类。

            2.复写run()方法。

            3.启动线程,使用start()方法

       3-2.实现接口Runnable接口。

            1.定义类(A)实现(implements)接口Runnable。

            2.重写run()方法。

            3.创建线程与类(A)创建联系,开启线程

4. 线程的创建---Thread类

         4-1.代码举例

          

public class MyThread extends Thread {
   public void run(){
      for(int i=0;i<10;i++)
        System.out.println(Thread.currentThread().getName()+"--"+i);
   }
}
结果:
main--0
Thread-0--0
main--1
Thread-0--1
main--2
Thread-0--2
Thread-0--3
main--3
Thread-0--4
main--4
Thread-0--5
main--5
Thread-0--6
main--6
Thread-0--7
main--7
Thread-0--8
main--8
Thread-0--9
main--9

 

从结果上可以看出,每次的运行结果都不一样,原因就是自定义的那个线程和主线程抢夺CPU,那一个先抢到CPU,那个就先执行。

      4-2.start()和run()的区别和联系

         联系:线程调用start()方法实际上是调用的run()方法,run()方法中存储的线程运行的代码

         区别:调用start()方法是启动线程,直接调用run()方法的话,那么就和调用普通的方法是一样的,没有启动线程。

        

             

public class MyThread extends Thread {
   public void run(){
     for(int i=0;i<10;i++)
       System.out.println(Thread.currentThread().getName()+"--"+i);
   }
}
public class Text {
  public static void main(String[] agrs) {
    MyThread tt = new MyThread();
    tt.run();
    for (int i = 0; i < 10; i++)
      System.out.println(Thread.currentThread().getName() + "--" + i);
 
  }
}

      这样的话,无论你运行多少次,那么结果都是一样的,因为就存在一个主线程,从结果你就可以看出的。

      4-3.复写run()

            run() 中存在的是线程运行的代码,对于主线程中运行的代码存储在main()方法中。

      4-4.疑问解答

          在主线程中,运行时候,也是按照顺序的。直到新的线程开启了,那么才会和存在线程抢夺CPU。

      

 
              

public class MyThread extends Thread {
   public void run(){
     for(int i=0;i<10;i++)
       System.out.println(Thread.currentThread().getName()+"--"+i);
   }
}
public class Text {
  /*
   * 主线程开始从上向下执行,直到执行到了tt线程,启动了tt线程,
   * 但是此时主线程已经运行结束了,所以运行结果都是一样的。
   * */
  public static void main(String[] agrs) {
    for (int i = 0; i < 10; i++)
      System.out.println(Thread.currentThread().getName() + "--" + i);
    MyThread tt = new MyThread();
    tt.start();
  }
}
public class Text1{
  /*
   * 主线程开始从上向下执行,开始就创建了线程,并且启动了tt线程,
   * 然后tt线程会和主线程抢夺CPU,谁抢到就会执行谁,所以此时运行结果是不确定的
   * */
  public static void main(String[] agrs) {
    MyThread tt = new MyThread();
    tt.start();
    for (int i = 0; i < 10; i++)
      System.out.println(Thread.currentThread().getName() + "--" + i);
   
  }
}

5.  线程状态

                        

6.  线程名称

       6-1.默认的线程

                   默认线程的名称是Thread-0,Thread-2…….。主线程的名称是:main

         

 
    

public class Text {
  public static void main(String[] agrs) {
    MyThread tt = new MyThread();
    System.out.println("默认的线程名称:"+tt.getName());
    //tt.start();
  System.out.println( "主线程的默认的名字:"+Thread.currentThread().getName());
   
  }
}

   6-2.自定义线程

    自定义线程名称和获得线程名称名

        设置线程名称:可以用setName()方法,可以用构造方法设置线程名称

获得线程名称:用getName()方法获得线程名称

Thread.currentThread()获得当前运行的线程对象

  

public class MyThread extends Thread {
  public MyThread (String name){//通过构造方法设置线程名称
    super(name);
  }
   public void run(){
   
   }
}
public class Text {
  public static void main(String[] agrs) {
    MyThread tt = new MyThread("线程A");
    System.out.println("线程名称:" + tt.getName());
    // tt.start();
    /*
     * 也可以通过setName()来设置线程名称
     */
    tt.setName("setName");
    System.out.println("线程名称:" + tt.getName());
  }
}
结果:
线程名称:线程A
线程名称:setName

7.  售票小例子

   

 public class Tick extends Thread {
  private int tick = 10;
 
  public void run() {
    while (tick > 0) {
      System.out.println(Thread.currentThread().getName() + "卖了第"
           + (tick--) + "张票");
    }
  }
}
public class Text {
  public static void main(String[] agrs) {
    new Tick().start();
    new Tick().start();//这样相当于开了3个线程,就是3个窗口
    new Tick().start();//但是这样相当于各个窗口买各自的票,而不是共享票
 
  }
}

这样的结果相当于买了40张票,但是本来就10张票,重复卖了

结果:

Thread-0卖了第10张票

Thread-2卖了第10张票

Thread-1卖了第10张票

Thread-1卖了第9张票

Thread-2卖了第9张票

Thread-0卖了第9张票

解决办法

          1. 把票(tick)定义成静态的,但是如果定义静态的话,但是静态变量声明周期长,不建议这样使用

   

        

 public class Tick extends Thread {
  private static int tick = 10;
 
  public void run() {
    while (tick > 0) {
      System.out.println(Thread.currentThread().getName() + "卖了第"
           + (tick--) + "张票");
    }
  }
}

         2.可以把值开启一个线程,结果没有错,但是和日常生活多个窗口共同卖票不符合

              

 public class Text {
  public static void main(String[] agrs) {
    new Tick().start();
  }
}

       3.使用实现Runnable接口线程处理此情况,最好了。具体的请查看  黑马程序员_<<线程(2)>>

 

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流!
--------------------


抱歉!评论已关闭.