Java技术基础

Java多线程基础

2019-01-17  本文已影响15人  oneape15

前言

在我们工作和学习的过程中,Java线程我们或多或少的都会用到,但是在使用的过程上并不是很顺利,会遇到各种各样的坑,这里我通过讲解Thread类中的核心方法,以求重点掌握以下关键技术点:

什么是进程和线程?

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。

相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。

多线程的优点

其实多线程从某方面可以等价于多任务,当你有多个任务要处理时,多个任务一起做所消耗的时间肯定比任务串行起来做,所消耗的时间短;下图可以很好的说明:


单任务运行环境与多任务运行环境比较

在我们现在的系统中,CPU的运行速度是很快的,其中很大的时间消耗是在等硬盘、IO输入、网络等资源;当多任务时,CPU完全可以在多个任务之间来回切换。使用的花费的时间远远少于所有任务需要消耗的少。

使用多线程

在Java的JDK包中,已经自带了对多线程技术的支持,可以非常方便地进行多线程的编程。实现多线程编程的方式主要有两种:

Runnable接口类源代码:

@FunctionalInterface
public interface Runnable {
   public abstract void run();
}

Thread类的主要源代码:

public class Thread implements Runnable {
  public static native Thread currentThread();
  public static native void yield();
  public static native void sleep(long millis) throws InterruptedException;
  public static void sleep(long millis, int nanos) throws InterruptedException {
    // ...
    sleep(millis);
  }
  public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
  }
   public Thread(Runnable target) {
      init(null, target, "Thread-" + nextThreadNum(), 0);
   }
  public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
  }

  public synchronized void start() {
    // ...
    start0(); 
    // ...
  }
  private native void start0();
  @Deprecated
  public final void stop() {
    // ...
  }
  public void interrupt() {
     // ...
  }
  public static boolean interrupted() {
     return currentThread().isInterrupted(true);
  }
  public boolean isInterrupted() {
      return isInterrupted(false);
  }
  private native boolean isInterrupted(boolean ClearInterrupted);
  public final native boolean isAlive();
  @Deprecated
  public final void suspend() {
        checkAccess();
        suspend0();
  }
  @Deprecated
  public final void resume() {
        checkAccess();
        resume0();
  }
}
这二种创建线程的方式有什么区别?

这个主要是因为Java类是单继承的,而接口可以支持多继承,使用Thread类的方式创建新线程时,最大的局限就是不支持多继承。所以具体选择哪种方式来创建线程,就看你是不是需要具体多继承的特性;其他没有本质的区别。

Thread详解

通过Thread的源代码,我们现在对其主要的的一些方法进行讲解一下

public Thread()
public Thread(Runnable target)
Thread(Runnable target, AccessControlContext acc)
public Thread(ThreadGroup group, Runnable target)
public Thread(String name)
public Thread(ThreadGroup group, String name)
public Thread(Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name, long stackSize)

private static long threadSeqNumber;
private static synchronized long nextThreadID() {
   return ++threadSeqNumber;
} 

在一个进程中,线程的ID是唯一的

在Java中有以下3种方法可以终止正在运行的线程。

  • 使用退出标志,使线程正常退出,即当run方法完成后线程终止。
  • 使用stop方法强行终止线程,但是不推荐使用该方法,因为stop和suspend及resume一样,都是作废过期的方法,使用它们可能产生不可预料的结果。
  • 使用interrupt方法中断线程。

java的线程优先级分为1~10这10个等级
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

  • 线程优先级具有继承特性, 比如A线程启动B线程,则B线程的优先级与A是一样的。
  • 优先级具有规则性,虽然我们使用setPriority()方法设置了优先级,但是真正执行的过程中,不会保证优先级高的线程绝对比优先级低的线程优先完成。即CPU尽量将执行资源让给优先级比较高的线程
    *优先级具有随机性,具优先级较高的线程不一定每一次都先执行完。

守护线程是一种特殊的线程,它的特性有“陪伴”的含义,当进程中不存在非守护线程了,则守护线程自动销毁。
典型的守护线程就是垃圾回收线程,当进程中没有非守护线程了,则垃圾回收线程则没有存在的必要了,自动销毁。
只要当前JVM实例中存在任何一个非守护线程没有结束,守护线程就在工作,只有当最后一个非守护线程结束时,守护线程才随着JVM一同结束工作。
通过调用Thread.setDaemon(true)设置是否为守护线程。

上一篇 下一篇

猜你喜欢

热点阅读