Java 程序设计 第八章 线程

简介: Java 程序设计 第八章 线程

第8章 线程

线程可以让一个程序同时执行多个任务,在实际程序应用地非常广泛。

8.1 理解线程

8.1.1进程的概念

了解线程前先了解一下进程,进程可以看成是程序的执行,可以把一个程序的执行过程看成是一个进程。

比如我们打开一个Word程序,就有一个Word程序进程。

8.1.2 线程的概念(此处是个人理解。)

一个进程可以有多个线程,同时执行多个任务。同样用Word举例,Word显示可以看成是一个线程,编辑可以看出是一个线程。

8.1.3 线程的生命周期

线程的生命周期有4种基本状态:

1.产生

2.中断

3.非中断(运行或可运行)

4.退出

8.2 线程类设计

8.2.1 线程API类图

Thread类是线程实现的主类,其核心过程方法由Runnable接口规范。

 

8.2.2  线程类Thread的构造方法

1.Thread(String threadName);  //创建指定名称的线程类

2.Thread();                              //线程类名称系统自动指定Thread-编号

3.Thread(Runnable target)  //target为目标对象,target需要实现Runnable接口,给出run()方法。

8.3 线程实现

线程的实现一般有两种方式:

(1)创建Thread类的子类,并重新定义run()方法,用户只要创建子类对象就能建立自己的线程。

(2)创建实现Runnable接口的类,并实现run()方法。

8.3.1 继承实现

方式一:继承Thread类

public class ThreadDemo extends Thread{
  public void run() {
    //线程代码实现
    System.out.println("线程执行");
  }
  public static void main(String[] args) {
    ThreadDemo th = new ThreadDemo();
    th.start();
  }
}

8.3.2接口实现

方式二:实现Runnable接口

 

public class ThreadDemo2{
  public static void main(String[] args) {
    Thread th  = new Thread(new MyThImpl());
    th.start();
  }
}
class MyThImpl implements Runnable{
  public void run() {
    //线程代码实现
    System.out.println("线程执行");
  }
}

8.4 线程控制

8.4.1 监控线程状态

线程状态在枚举类型Thread.State中定义。

NEW:新创建,还没调用start()

RUNNABLE:run()中代码被执行

BLOCKED:阻塞,等待解锁

WAITING:另一个线程运行,本线程等待

TIMED_WAIYING:等待到指定时间

TERMINATED:线程退出run()

获取线程状态方法:

public Thread.State getState()

 

8.4.2 线程休眠

Thread的sleep()方法

public class sleep1 {
  public static void main(String[] args) throws InterruptedException {
    for(int i=0;i<20;i++) {
      System.out.println("main"+i);
      Thread.sleep(1000);
    }
  }
}

注意:(1)sleep是静态方法,睡眠的是当前运行的线程、

 

8.4.3 中断线程

public void interrupt() :中断当前阻塞与等待状态,强制线程抛出异常。

 

8.4.4 阻塞进程 join()

void join(): 当前线程等待加入该线程后面,等待该线程终止

void join(long millis):当前线程等待该线程终止的时间最长为millis毫秒,如果超时还没执行完,当前线程也会进入就绪状态。

void join(long millis, int nanos);等待时间millis毫秒+nanos纳秒

8.4.5线程等待和唤醒

public final void wait() throws InterruptedException
public final void wait(long timeout,int nanos)throws InterruptedException
void notify()
void notifyAll()

如果线程等待用sleep(),唤醒用interrupt()

等待用join(),唤醒用interrupt()

等待用wait(),唤醒用notify();

 

8.4.6线程终止

当前线程放弃调度执行权力,等待下次排队执行。

public static void yield()

 

..线程控制综合实例

 

import java.util.Scanner;
public class sleep1 {
  private static int data = -1;
  private static Thread thread = new Thread(new Runnable() {
    public void run() {
      System.out.println("线程已经启动,输入0开始计数");
      for(int i=10;i>0;i--) {
        while(data != 0) {
          Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+":"+i);
        try {
          Thread.sleep(100);
        }catch(InterruptedException e) {
          e.printStackTrace();
        }
        
      }
    }
  });
  public static void main(String[] args) {
    thread.start();
    Scanner in = new Scanner(System.in);
    while(data == -1) {
      try {
        data=Integer.parseInt(in.nextLine());
        if(data!=0) {
          System.out.println("enter 0 to start counting");
          data = -1;
        }
      }catch(NumberFormatException e) {
        System.out.println("请输入整数");
      }
    }
  in.close(); 
  }
}
 
 
 

8.5 线程属性

8.5.1 优先级

优先级较高的线程获取CPU资源的概率较大。

每个线程默认的优先级和父线程相同。

Thread类提供setPriority(int newPriority和getPriority)和getPriority()方法来设置和得到优先级。

setPriority的参数时一个整数,范围1~10. (10最高)。

优先级实例:

 
public class priority1 {
  public static void main(String[] args) {
    new MyThread("低级",1).start();
    new MyThread("高级",10).start();
  }
}
class MyThread extends Thread{
  public MyThread(String name,int pro) {
    super(name);
    setPriority(pro);
  }
  public void run() {
    for(int i=0;i<=100;i++) {
      System.out.println(this.getName()+"线程第"+i+"次执行");
    }
  }
}

多次运行可以发现,多数情况下优先级高的先运行完成。

8.5.2 守护线程

Java中有两类线程:用户线程User Thread 和 守护线程Daemon Thread

守护线程具有最低优先级,为系统其它对象提供服务。

一般不会自己操作守护进程。

 

8.6线程同步

8.6.1Synchronized同步方法和同步代码块

保护某段代码只能同时被一个线程执行的技术成为线程同步。

关键字synchronized是Java内部实现的一个简单锁,可以用synchronized锁定一段代码:

public static void biz() {
    synchronized(Object.class) {
      a++;
      b++;
      if(a!=b) {
        System.out.println(a+"!="+b);
      }
    }
  }

或者锁定整个方法:

  synchronized public static void biz() {
      a++;
      b++;
      if(a!=b) {
        System.out.println(a+"!="+b);
      }
    
  }

8.6.2 同步变量volatile关键字

Java变量前可以加修饰语volatile,volatile的主要目的是解决成员变量的多线程访问同步问题。

在读取加了volatie修饰的变量时,会直接从内存读取。

但volatile不保证对变量的操作是原子操作。

Java提供java.util.concurrent.automic包,提供了基本类型与引用类型的原子性操作封装类:

AtomicBoolean

AtomicInteger

AtomicIntegerArray

...

 

8.6.3线程锁Lock接口及ReentrantLock类

8.6.4 死锁

不同线程都在等待那些不可能被释放的锁时,就成了死锁。

构成死锁的典型是锁交叉。


相关文章
|
11天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
20天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
7天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
28 9
|
10天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
7天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
10天前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
24 3
|
9天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
10天前
|
Java
java小知识—进程和线程
进程 进程是程序的一次执行过程,是系统运行的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程 线程,与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比
22 1
|
10天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
11天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
39 1