java线程的基础知识

java线程的基础知识

目录

前言

一、基础概念

1.1 程序、进程、线程

1.1.1程序

1.1.2进程

1.1.3线程

1.2 单核CPU与多核CPU

1.3 并行和并发

1.4 多线程的优缺点

二、线程的分类

2.1 用户线程

2.2 守护线程

三、线程的创建方式

3.1 声明一个子类继承Thread ,重写run方法

3.2 声明一个子类实现Runable接口,实现run方法

3.3 实现Callable接口,重写call方法

3.4 注意事项

四 创建方式的比较

4.1优先使用哪种方式

4.2 两种方式的联系

五、线程的生命周期

总结


前言

一、基础概念

1.1 程序、进程、线程

1.1.1程序

1.1.2进程

1.1.3线程

1.2 单核CPU与多核CPU

1.3 并行和并发

1.4 多线程的优缺点

二、线程的分类

2.1 用户线程

2.2 守护线程

2.3 关联

三、线程的创建方式

3.1 声明一个子类继承Thread ,重写run方法

3.2 声明一个子类实现Runable接口,实现run方法

3.3 注意事项

四 创建方式的比较

4.1优先使用哪种方式

4.2 两种方式的联系

五、线程的生命周期

总结


前言

随着计算机技术的不断发展,高并发的技术要求越来越多严格,但这都离不开基础服务核心的支持,那就是线程,本文就根据自己的见解,来说一说java的线程。


一、基础概念

1.1 程序、进程、线程

1.1.1程序

为了完成某个任务,用计算机的编程语言编写的可运行代码集合。是一个静态的对象。例如我们常用的微信,就是一个通讯的程序。

1.1.2进程

程序运行的一个过程。当运行了微信程序,就相当于开启了一个微信运行的进程,当进程被强迫关闭的时候,该程序也会被强制关闭。

1.1.3线程

程序内部执行的一条执行路径。例如微信程序中,接收某个朋友的一条信息的过程就是一个线程。多线程就是在同一个单位时间内,可以同时进行多个线程操作,例如在微信在同一时间内可以接收多个朋友发送的信息。

1.2 单核CPU与多核CPU

单核CPU,在单位时间内,只能执行一个线程任务。多线程任务在单核cpu的电脑中执行,实际上也是会执行完一个线程再执行另外一个线程。

多核CPU,在单位时间内,可以执行多个线程任务,只有多核CPU,才可以发挥多线程的效率。

1.3 并行和并发

并行,多个cpu并行执行多个任务。例如,多个人同时在做不同的事情。

并发,单个cpu同时执行多个任务。例如,商品的秒杀。多个人在做同一个事情。

1.4 多线程的优缺点

缺点,单cpu情况下,执行多线程的时间会比执行一个个单线程的时间慢。

优点,可以在同一个时间内,同时进行多个操作。可以有效避免主线程阻塞的问题。增强用户的体验度。


二、线程的分类

线程可以分为守护线程和用户线程。两者各方面都是相同的, 守护线程依赖于用户线程,若jvm中都只剩下守护线程的时候,那么jvm也将退出了。

2.1 用户线程

用户线程就是我们平时使用的用来处理逻辑的线程。例如,平时运行program程序中的main方法里的主线程。

2.2 守护线程

最常见的就是jvm的垃圾回收线程。


三、线程的创建方式

一共有两种方式来创建java线程,在java8 api文档中说到。其实我觉得最终的实质也就是一种方式去创建线程,都是需要new Thread ,然后去调用它的start方法。只是它的run方法,实现的方式不同而已。

java8 API

3.1 声明一个子类继承Thread ,重写run方法

class PrimeThread extends Thread {
      long minPrime;
      PrimeThread(long minPrime) {
          this.minPrime = minPrime;
      }

      public void run() {
           // compute primes larger than minPrime
           . . .
      }
}

实例化子类,并调用它的start方法

PrimeThread p = new PrimeThread(143);
p.start();

3.2 声明一个子类实现Runable接口,实现run方法

class PrimeRun implements Runnable {
    long minPrime;
    PrimeRun(long minPrime) {
         this.minPrime = minPrime;
    }

    public void run() {
       // compute primes larger than minPrime
              . . .
    }
}

实例化子类,并传到实例化线程类中。

PrimeRun p = new PrimeRun(143);
new Thread(p).start();

3.3 实现Callable接口,重写call方法

官方文档说到,A task that returns a result。是一个有返回的任务。The Callable interface is similar to Runnable。它和Runnable接口很相似。需要结合Interface Future<V>接口来使用,通过调用feature.get方法来获得任务的返回值。

interface ArchiveSearcher { String search(String target); }
 class App {
   ExecutorService executor = ...
   ArchiveSearcher searcher = ...
   void showSearch(final String target)
       throws InterruptedException {
     Future<String> future
       = executor.submit(new Callable<String>() {
         public String call() {
             return searcher.search(target);
         }});
     displayOtherThings(); // do other things while searching
     try {
       displayText(future.get()); // use future
     } catch (ExecutionException ex) { cleanup(); return; }
   }
 }

 

3.4 注意事项

线程start后,不能重复多次进行start 方法调用。

四 创建方式的比较

4.1优先使用哪种方式

实际应用中,建议选择实现Runable接口的方式。主要原因有两个。

其一,继承接口的方式,可以打破了类单一继承的局限性。

其二,多线程之间的数据共享,可以通过共享单一的Runable实现类,而达到共享资源的目的。非常适合多个相同线程来处理同一份资源的情况。

4.2 两种方式的联系

Thread类中也是继承了Runnable的接口,方式二,也是实现了Runnable的接口。不管哪一种创建方式,都是需要实现run方法。

五、线程的生命周期

一个完整的线程会经历五种线程状态,创建》就绪 》运行》阻塞》死亡。

创建

当一个Thread子类被声明创建时。

PrimeThread p = new PrimeThread(143);

就绪

当线程调用start方法后,进入线程队列等待,并还没有得到cpu分配资源。

p.start();

运行

当线程获得cpu分配的资源后,执行run方法。

public void run() {
   // compute primes larger than minPrime
}

阻塞

当因为某些特定的原因,cpu让出了执行的资源,线程被挂起,就形成了阻塞的状态。例如线程1 join 线程2,则线程1被挂起,就形成了阻塞状态。sleep(long time) ,等待同步锁,wait,

死亡

当线程完成了所有的操作,或者被强迫调用终止的方法,或是因为出现了异常而导致结束。


总结

简单的说明了一下java线程的基础知识,也不知道对不对,共勉。下一篇文章,继续探讨线程的安全问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值