Java 线程学习记录(未完)

来源:互联网 发布:淘宝微博推广平台 编辑:程序博客网 时间:2024/05/22 00:15

Java 线程学习记录

概念

  • 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。
  • 线程是指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。

java中的线程

  • Java中,“线程”指两件不同的事情:
    • java.lang.Thread类的一个实例线程
    • 线程的执行
  • 使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。一个Thread类实例只是一个对象,像Java中的任何其他对象一样,具有变量和方法,生死于堆上。
  • Java中,每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行着。一个Java应用总是从main()方法开始运行,mian()方法运行在一个线程内,它被称为主线程。
  • 一旦创建一个新的线程,就产生一个新的调用栈。
  • 线程总体分两类:用户线程和守候线程。
  • 当所有用户线程执行完毕的时候,JVM自动关闭。但是守候线程却不独立于JVM,守候线程一般是由操作系统或者用户自己创建的

java线程的创建和启动

创建java.lang.Thear类

public class Main_App extends Thread{    public int n;    public Main_App(int n){        this.n = n;        new Thread(this).start(); //调用Thread的start()方法执行run()方法    }    public void run(){        System.out.println("******************************");        System.out.println(this.n);        System.out.println(Thread.currentThread()); //Thread.currentThread()获取当前线程的名称    }    public static void main(String[] args){        String TestString = "jwiejiealjdijfeij";        int i;        int m = TestString.length();        while(true){            for( i = 0 ; i < m ; i++){                if(TestString.charAt(i) == 'j'){                    new Main_App(i);                }            }        }    }
  • 运行结果
//得到得结果顺序会不一样,线程执行顺序由JVM线程调度程序决定Thread[Thread-17939,5,main]******************************0Thread[Thread-17941,5,main]******************************9Thread[Thread-17945,5,main]******************************4Thread[Thread-17943,5,main]******************************12Thread[Thread-17947,5,main]******************************16Thread[Thread-17949,5,main]······

实现java.lang.Runnable接口

  • 创建主类Main_App.java
public String TestString = "jwiejiealjdijfeij";    public static void main(String[] args) {        Main_App app = new Main_App();        int i =0;        int m = app.TestString.length();        while(true){            for( i = 0 ; i < m ; i++){                if(app.TestString.charAt(i) == 'j'){                    new Test(i);                }            }        }    }
  • 创建Test.java继承Runnable
public String TestString = "jwiejiealjdijfeij";    public static void main(String[] args) {        Main_App app = new Main_App();        int i =0;        int m = app.TestString.length();        while(true){            for( i = 0 ; i < m ; i++){                if(app.TestString.charAt(i) == 'j'){                    new Test(i);                }            }        }    }
  • 运行结果
//得到得结果顺序会不一样,线程执行顺序由JVM线程调度程序决定----------------------------        12           Thread[Thread-8939,5,main]----------------------------        9           Thread[Thread-8938,5,main]----------------------------        4           Thread[Thread-8937,5,main]----------------------------        0           Thread[Thread-8941,5,main]
  • 常见问题

    1、线程的名字,一个运行中的线程总是有名字的,名字有两个来源,一个是虚拟机自己给的名字,一个是你自己的定的名字。在没有指定线程名字的情况下,虚拟机总会为线程指定名字,并且主线程的名字总是mian,非主线程的名字不确定。
    2、线程都可以设置名字,也可以获取线程的名字,连主线程也不例外。
    3、获取当前线程的对象的方法是:Thread.currentThread();
    4、在上面的代码中,只能保证:每个线程都将启动,每个线程都将运行直到完成。一系列线程以某种顺序启动并不意味着将按该顺序执行。对于任何一组启动的线程来说,调度程序不能保证其执行次序,持续时间也无法保证。
    5、当线程目标run()方法结束时该线程完成。
    6、一旦线程启动,它就永远不能再重新启动。只有一个新的线程可以被启动,并且只能一次。一个可运行的线程或死线程可以被重新启动。
    7、线程的调度是JVM的一部分,在一个CPU的机器上上,实际上一次只能运行一个线程。一次只有一个线程栈执行。JVM线程调度程序决定实际运行哪个处于可运行状态的线程。
    众多可运行线程中的某一个会被选中做为当前线程。可运行线程被选择运行的顺序是没有保障的。
    8、尽管通常采用队列形式,但这是没有保障的。队列形式是指当一个线程完成“一轮”时,它移到可运行队列的尾部等待,直到它最终排队到该队列的前端为止,它才能被再次选中。事实上,我们把它称为可运行池而不是一个可运行队列,目的是帮助认识线程并不都是以某种有保障的顺序排列唱呢个一个队列的事实。
    9、尽管我们没有无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。

线程的优先级和线程让步yield()

  • 线程的让步是通过Thread.yield()来实现的。yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程
  • 要理解yield(),必须了解线程的优先级的概念。线程总是存在优先级,优先级范围在1~10之间。JVM线程调度程序是基于优先级的抢先调度机制。在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。但这仅仅是大多数情况。
  • 注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。

  • 当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。

  • 设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。可以通过setPriority(int newPriority)更改线程的优先级。例如:
Thread t = new MyThread();t.setPriority(8);t.start();
  • 线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。然而,1~10之间的值是没有保证的。一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。
  • 线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围:
    • static int MAX_PRIORITY
      线程可以具有的最高优先级。
    • static int MIN_PRIORITY
      线程可以具有的最低优先级。
    • static int NORM_PRIORITY
      分配给线程的默认优先级。