Java基础之多线程详解

简介: Java基础之多线程详解

Java多线程是抢占式,谁的优先级高,谁就先执行。


Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例。


Thread类

构造方法:  

public Thread() :分配一个新的线程对象。


public Thread(String name) :分配一个指定名字的新的线程对象。


public Thread(Runnable target) :分配一个带有指定目标新的线程对象。


public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。


常用方法:

public String getName() :获取当前线程名称。


public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。


public void run() :此线程要执行的任务在此处定义代码。


public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。


public static Thread currentThread() :返回对当前正在执行的线程对象的引用。


public  void Join()    终止该线程


创建并启动多线程的步骤

一、使用基类Thread

1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体。


2. 创建Thread子类的实例,即创建了线程对象


3. 调用线程对象的start()方法来启动该线程


public class MyThread extends Thread{
  @Override
  public void run() {
  for( int i = 0;i < 20;i++){
    System.out.println("run"+i);
  }
  }
}
public static void main (String[]args){
  //多线程
  MyThread my1 = new MyThread();
  //my1.run();调用run()方法     单线程
  my1.start();//执行run()方法   多线程   新开一个栈空间
  //main执行
  for(int i  = 0;i < 20;i++){
  System.out.println("main"+i);
  }
}

二、使用Runnable接口

1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。


2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。


3. 调用线程对象的start()方法来启动线程


public class DemoRunnableImpl implements Runnable{//步骤一
  @Override
  public void run(){
  for(int i = 0;i < 5;i++){
    System.out.println(Thread.currentThread().getName()+"-->"+i);
  }
  }
}
public static void main (String[] args){
  DemoRunnableImpl demo =new DemoRunnableImpl();//步骤二
  Thread thread= new Thread (demo);
  thread.start();//步骤三
}

三、使用匿名内部类

public static void main(String[] args){
  //线程的父类是Thread
  new  Thread(){
  @Override
  public void run(){
    for(int i = 0;i < 5;i++){
    System.out.println(Thread.currentThread().getName()+"小小张自由");
    }
  }
  }.start();
  //线程的接口是Runnable
  Runnable r = new Runnable(){
  @Override
  public void run(){
    for(int i = 0;i < 5;i++){
    System.out.println(Thread.currentThread().getName()+"身体健康");
    }
  }
  };
  new Thread(r).start();
}

解决线程安全问题

线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无操作,一般来说,这个全局变量是线程安全的。


若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。


synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。


锁对象 可以是任意类型。多个线程对象,要使用同一把锁。在任何时候,最多运行一个线程拥有同步锁,谁拿到锁就进入代码块,其他线程只能等待。


一、同步代码块

//语法格式
synchronized(同步锁){
  //需要同步操作的代码
}
//示例
private int cont = 100;
Object obj = new Object();
@Override
public void run(){
  synchronized(obj){ //被锁住的代码
  while(cont>0){
    //线程休眠10毫秒
    try{
    Thread.sleep(10);
    }catch(Exceptione){
    System.out.println(e.getMessage());
    }
    System.out.println(Thread.currentThread().getName()+"正在抢第"+cont+"票");
    cont--;
  }
  }
}

二、同步方法

将需要同步操作的代码,抽出来。放到一个方法中。Run()方法再调用同步方法


public synchronized void method(){ 
  //可能会产生线程安全问题的代码 
}

三、锁(Lock)机制

    1.在成员位置创建一个ReentrantLock对象


    2.在可能出现安全问题的代码前调用Lock接口中的方法Lock获取锁


    3.在可能出现安全问题的代码后调用Lock接口中的方法unLock释放锁


public class DemoRunnableImpl implements Runnable {
    private int cont = 100;
    Lock lock=new ReentrantLock();//创建一个ReentrantLock对象
    @Override
    public void run() {
        lock.lock();//获取锁
        while (cont > 0) {
            //线程休眠10毫秒
            try {
                Thread.sleep(10);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            System.out.println(Thread.currentThread().getName() + "正在抢第" + cont + "票");
            cont--;
        }
        lock.unlock();//释放锁
    }
}

线程之间的通信

   多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行, 那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。


线程状态概述

image.png


等待和唤醒案例——生产者和消费者

       1.顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行


       2.同步使用的锁对象必须保证唯一


       3.只有锁对象才能能用wait()和notify()方法


public static void main(String[] args) {
        Object obj=new Object();//锁对象
        //消费者
        new Thread(){
            @Override
            public void run() {
                while (true){
                    synchronized (obj){  //同步代码段
                        System.out.println("告知老板要的包子种类和数量");
                        try {
                            obj.wait();//线程等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //唤醒之后执行的代码
                        System.out.println("包子已经做好了,开吃!");
                    }
                }
            }
        }.start();
        //生产者
        new Thread(){
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(5000); //花5s做包子
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj){ //同步代码段
                        System.out.println("老板5秒钟包子做好了,可以吃包子了!");
                        //做好包子,调用notify方法,唤醒顾客吃包子
                        obj.notify();
                        System.out.println("---------------------");
                    }
                }
            }
        }.start();
    }
相关文章
|
2天前
|
缓存 安全 Java
7张图带你轻松理解Java 线程安全,java缓存机制面试
7张图带你轻松理解Java 线程安全,java缓存机制面试
|
1天前
|
Java
深入理解Java并发编程:线程池的应用与优化
【5月更文挑战第18天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将了解线程池的基本概念,应用场景,以及如何优化线程池的性能。通过实例分析,我们将看到线程池如何提高系统性能,减少资源消耗,并提高系统的响应速度。
11 5
|
1天前
|
消息中间件 安全 Java
理解Java中的多线程编程
【5月更文挑战第18天】本文介绍了Java中的多线程编程,包括线程和多线程的基本概念。Java通过继承Thread类或实现Runnable接口来创建线程,此外还支持使用线程池(如ExecutorService和Executors)进行更高效的管理。多线程编程需要注意线程安全、性能优化和线程间通信,以避免数据竞争、死锁等问题,并确保程序高效运行。
|
1天前
|
存储 Java
【Java】实现一个简单的线程池
,如果被消耗完了就说明在规定时间内获取不到任务,直接return结束线程。
8 0
|
1天前
|
安全 Java 容器
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第18天】随着多核处理器的普及,并发编程变得越来越重要。Java提供了丰富的并发编程工具,如synchronized关键字、显式锁Lock、原子类、并发容器等。本文将深入探讨Java并发编程的核心概念,包括线程安全、死锁、资源竞争等,并分享一些性能优化的技巧。
|
1天前
|
安全 Java 开发者
Java中的多线程编程:理解与实践
【5月更文挑战第18天】在现代软件开发中,多线程编程是提高程序性能和响应速度的重要手段。Java作为一种广泛使用的编程语言,其内置的多线程支持使得开发者能够轻松地实现并行处理。本文将深入探讨Java多线程的基本概念、实现方式以及常见的并发问题,并通过实例代码演示如何高效地使用多线程技术。通过阅读本文,读者将对Java多线程编程有一个全面的认识,并能够在实际开发中灵活运用。
|
1天前
|
算法 Java 程序员
Java中的线程同步与并发控制
【5月更文挑战第18天】随着计算机技术的不断发展,多核处理器的普及使得多线程编程成为提高程序性能的关键。在Java中,线程是实现并发的一种重要手段。然而,线程的并发执行可能导致数据不一致、死锁等问题。本文将深入探讨Java中线程同步的方法和技巧,以及如何避免常见的并发问题,从而提高程序的性能和稳定性。
|
2天前
|
存储 安全 Java
Java多线程基础知识总结,36岁老码农现身说法
Java多线程基础知识总结,36岁老码农现身说法
|
2天前
|
Java 测试技术
Java多线程的一些基本例子
【5月更文挑战第17天】Java多线程允许并发执行任务。示例1展示创建并启动两个`MyThread`对象,各自独立打印&quot;Hello World&quot;。示例2的`CounterExample`中,两个线程(IncrementThread和DecrementThread)同步地增加和减少共享计数器,确保最终计数为零。这些例子展示了Java线程的基本用法,包括线程同步,还有如Executor框架和线程池等更复杂的用例。
9 0
|
2天前
|
Java
阅读《代码整洁之道》总结(1),java多线程面试
阅读《代码整洁之道》总结(1),java多线程面试