Java中的线程

Posted mb62d3c286f15ed

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的线程相关的知识,希望对你有一定的参考价值。

目录

​线程​

​一个线程的生命周期​

​线程的创建与启动​

​线程的终止​

​线程的同步机制​

​线程的通知机制​


线程

一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

一个线程的生命周期

线程是一个动态执行的过程,它也有一个从产生到死亡的过程。

下图显示了一个线程完整的生命周期。

Java中的线程_阻塞状态

  • 新建状态:使用new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
  • 就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
  • 运行状态:如果就绪状态的线程获取 CPU 资源,就可以执行run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
  • 阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
  • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
  • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
  • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
  • 死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

线程的创建与启动

Java 提供了三种创建线程的方法:

  • 通过实现 Runnable 接口;
  • 通过继承 Thread 类本身;
  • 通过 Callable 和 Future 创建线程。

方法一:实现Runnable接口

这是因为 java 不允许多重继承,如果你的类已经继承于别的类,又要作为线程来运行,则可以使用这种方式

public class Hello implements  Runnable
public void run()
//填写要干的事


Hello obj=new Hello();
Thread t=new Thread(obj);
t.start(); //线程的启动

方法二: 继承 Thread 类

public class Hello  extends Thread
public void run()
//填写要干的事


new Hello().start; //线程的启动

方法三:通过 Callable 和 Future 创建线程

  • 1. 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
  • 2. 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
  • 3. 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
  • 4. 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。

创建线程的三种方式的对比:

  • 采用实现 Runnable、Callable 接口的方式创建多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。
  • 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。

线程的终止

当一个线程的start()调用后,线程为Alive状态。当一个线程的主函数run()退出后,线程死亡(Dead);想让一个线程终止,就是要想办法让它从run()中退出来。当一个线程在sleep的时候,必须使用t.interrupt()来中断目标线程才可以使线程退出。等待线程的退出t.join();

//线程的终止
public class Test1 extends Thread
public boolean quitflag=false;
public void run()

for(int i=0;i<10;i++)
if(quitflag)
break;

System.out.println("---------");
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();





public class Hello
public static void main(String[] args)
// TODO 自动生成的方法存根
Test1 t1=new Test1();
t1.start();
//接受用户输入 输入后终止线程
InputStreamReader m=new InputStreamReader(System.in);
BufferedReader read=new BufferedReader(m);
try
read.readLine();
read.close();
t1.quitflag=true; //线程终止
t1.interrupt(); //使正在sleep的线程终止
t1.join(); //等待线程退出
catch (Exception e)
// TODO 自动生成的 catch 块
e.printStackTrace();

System.out.println("结束了");

线程的同步机制

当两个或多个线程同时访问一个对象时,可能发生数据不同步的现象。为了实现多线程对同一对象的同步访问,引入互斥锁的概念。

synchronized(lock)               //申请锁

//关键代码
  • 若别的线程正持有该锁,则本线程阻塞等待
  • 若此锁空闲,则本线程持有锁,进入大括号执行,完毕后释放锁

线程的通知机制

wait/notify 通知机制 

  1. 调用 wait(),notify(),notifyAll()时需要先对调用对象加锁。
  2. 调用wait()方法后,线程由RUNNING变为WAITING,并将当前线程放置于对象等待队列,释放锁
  3. notify(),notifyAll()方法被调用后,等待线程依然不会从wait()方法返回,而是等调用notify(),notifyAll()的线程释放该锁之后,等待线程才有机会从wait()返回。
  4. notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而 notifyAll()方法则是把所有等待线程从等待队列中移到同步队列中,被移动的线程的状态由WAITING变成BLOCKED
  5. 从wait()方法返回的前提是获得了调用对象的锁。
public class Test1 
static boolean flag=true;
static Object lock=new Object();

public static void main(String[] args)
One a=new One();
a.start();
Two b=new Two();
b.start();


static class One extends Thread
public void run()
synchronized(lock)
while(flag)
try
System.out.println("flag is true");
lock.wait(); //线程等待,释放锁
catch (InterruptedException e)
e.printStackTrace();


System.out.println("结束");



static class Two extends Thread
public void run()
synchronized (lock)
System.out.println("flag is false");
flag=false;
lock.notify();
System.out.println("notify之后,不会立即退出!");





以上是关于Java中的线程的主要内容,如果未能解决你的问题,请参考以下文章

随笔⑧ java中的存根类 --- Stub

什么是“服务器”上的存根,骨架是什么意思?

Wsdl 可选参数在生成的 java 存根代码中成为必需的

Blackberry应用程序中的Web服务存根

存根的 gRPC 并发

java多线程基础