Java中的多线程

本文介绍了Java中的多线程概念,包括何时需要使用多线程及其优缺点。接着讨论了线程同步的重要性,通过示例解释了同步监视器的工作原理,并介绍了synchronized关键字和Lock接口。此外,还提到了死锁问题和线程通信的wait、notify、notifyAll方法。最后,文章以生产者/消费者问题为例,展示了线程如何协作完成任务。
摘要由CSDN通过智能技术生成

概念

多线程是指程序当中包含多个执行单元,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个线程创建多个并行执行的线程来完成各自的任务。

何时需要多线程
程序需要同时执行两个或多个任务。

程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。

需要一些后台运行的程序时。

多线程的优点
提高程序的响应

提高CPU的利用率

改善程序的结构,将复杂的任务分为多个线程,独立运行。

多线程的缺点
线程也是程序,所以线程也是需要占用内存,线程越多占用内存也是越多的。

多线程是需要协调和管理,所以这也是需要CPU时间跟踪线程的。

线程之间对共享资源的访问会互相影响,必须解决竞用共享资源的问题。

线程同步

先看下面的一段代码:
在这里插入图片描述

在这样的输出绝对是有问题的。

所以在处理多线程的问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象。这时候我们就需要线程的同步。线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面的线程使用完毕,下一个线程再使用。

由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突的问题,为了保证数据在方法中被访问的正确性,在访问时加入锁机制synchronized,在当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可。

这里也存在下面的问题:

  1. 一个线程持有锁会导致其他所有需要此锁的线程挂起。
  2. 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延迟,引起性能问题。
  3. 如果一个优先级高的线程等待的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能问题。

在Java中实现同步
使用synchronized(同步监视器)这个关键字来同步方法或代码块

synchronized(同步监视器){
}

synchionized还可以放在方法声明中,表示整个方法,为同步方法。

public synchionized void show(Sting name){
//需要同步的代码
}

同步代码块,执行完毕后,同步对象(锁)就会自动释放
在这里插入图片描述

当然在synchronized的时候,也可以直接传进去关键字this,表示当前的。只要表示出唯一性就可以了。

同步方法:

public class TicketThread implements Runnable {
   
    static int num = 10;

    @Override
    public void run() {
   
        while (true) {
   
            if (num > 0) {
   
                print();
            } else {
   
                break;
            }
        }
    }

    //在修饰方法的时候,同步对象(锁),默认的是this,一旦创建多个线程对象就崔出现一些问题(只针对继承Thread类的方式)
    public synchronized void print() {
   
        if (num > 0) {
   
            try {
   
                Thread.sleep(1000);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "售出票:" + num);
            num--;
        }
    }
}

在这里插入图片描述

当然上面写的都是实现Runnable接口来实现的。
当然还是可以继承Thread类来实现的,在用thread来写的时候,一定要注意好只能由1个来实现的,该加static的时候就要加static来修饰,使得虽然创建了多个,但实际只能还是一个存在的。

上面代码中有提到的同步监视器是什么呢?
同步监视器可以是任何对象,但必须保证唯一,保证多个线程获得的是同一个对象(锁)

同步监视器的执行过程:

  1. 第一个线程访问,就锁定同步监视器,执行其中的代码
  2. 第二个线程访问,发现同步监视器被锁定的话,就无发访问
  3. 第一个线程结束访问,就解锁了同步监视器。
  4. 第二个线程访问,发现同步监视器没有锁,就可能正常访问,并加锁。

锁机制

上面提到的synchronized就是一个隐式的加锁,释放锁。

在这提到到的Lock是可以显示的加锁,释放锁的,但只能锁定代码块。

Lock:
是从jdk 1.5开始的,Java提供了更强大的线程同步机制-通过显示的定义同步锁对象来实现同步。同步锁使用Lock对象充当。

java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独立访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。

ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentranlLock,可以显示加锁,释放锁。
对我们上面写的TicketThread类的代码做做修改:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class 
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Java 多线程可以通过创建 Thread 类的实例来实现。具体步骤如下: 1. 创建一个实现 Runnable 接口的类,该类实现 run() 方法。 ```java public class MyRunnable implements Runnable { public void run() { // 执行线程的操作 } } ``` 2. 创建一个 Thread 实例,并将实现了 Runnable 接口的类作为构造函数的参数。 ```java MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); ``` 3. 启动线程。 ```java thread.start(); ``` 此外,还可以通过继承 Thread 类来实现多线程。具体步骤如下: 1. 创建一个继承自 Thread 类的类,重写 run() 方法。 ```java public class MyThread extends Thread { public void run() { // 执行线程的操作 } } ``` 2. 创建 MyThread 的实例。 ```java MyThread myThread = new MyThread(); ``` 3. 启动线程。 ```java myThread.start(); ``` 在多线程的使用,需要注意线程安全的问题,比如共享变量的访问、同步操作等。可以使用 synchronized 关键字或者 Lock 接口来保证线程安全。 ### 回答2: 在Java多线程的使用是指程序同时运行多个线程,每个线程执行自己的任务。Java多线程的使用可以带来以下几点好处: 1. 提高程序的效率:多线程可以对多个任务进行并发处理,提高程序的运行效率。例如,可以将网络请求和UI界面分别放在两个不同的线程,这样即使网络请求比较耗时,UI界面也能进行响应,不会出现界面假死的情况。 2. 充分利用系统资源:多线程可以充分利用系统的处理器资源,提高系统的利用率。在多核处理器上运行多个线程,可以让每个核心都得到充分利用,提高系统的整体性能。 3. 实现异步编程:多线程可以实现异步编程,即一个线程执行后续操作,不需要等待另一个线程的完成。这样可以提高程序的响应速度。例如,可以使用多线程来进行文件下载,下载过程可以同时进行其他操作。 4. 处理复杂的并发情况:在一些需要处理多个并发操作的场景多线程可以提供更好的解决方案。例如,在并发访问共享资源的情况下,使用线程锁可以保证对共享资源的安全访问,避免数据冲突和一致性问题。 Java使用多线程可以通过创建Thread类的实例或者实现Runnable接口来实现。通过继承Thread类来创建线程,需要重写run方法,在run方法定义线程要执行的任务。通过实现Runnable接口来创建线程,需要实现run方法,并将实现了Runnable接口的对象作为参数传递给Thread类的构造方法。 总之,Java多线程的使用使得程序可以同时执行多个任务,提高了程序的效率和用户体验,并且能够处理复杂的并发情况。但需要注意多线程的安全性和线程之间的协作,避免出现数据冲突和一致性问题。 ### 回答3: Java多线程的使用是指在一个程序同时执行多个任务或者同时处理多个请求。多线程可以提高程序的并发性和响应性,可以将耗时的操作和任务分配给不同的线程来执行,从而提高程序的运行效率。 在Java多线程的使用主要依靠Thread类或者实现Runnable接口来创建线程。可以通过继承Thread类创建一个线程类,并重写run方法,在run方法定义需要执行的任务;也可以实现Runnable接口,创建一个Runnable对象,然后将该对象作为参数传递给Thread类的构造方法,创建一个线程对象。 使用多线程的好处是可以充分利用处理器的多核特性,同时进行多个任务,提高程序的运行效率。多线程还可以提高程序的响应性,当程序有耗时的操作时,可以将其放在一个独立的线程执行,防止主线程被阻塞,提高用户体验。 然而,多线程的使用也存在一些问题。首先是线程安全问题,多个线程同时访问共享资源可能导致数据不一致或者数据损坏。为解决这个问题,可以使用同步机制,如synchronized关键字或Lock接口,保证在同一时间只有一个线程能够访问共享资源。其次,多线程的创建和销毁会消耗系统资源,如果线程数量过多,可能会影响系统性能。因此,在使用多线程时应该合理控制线程的数量。另外,线程之间的协调和通信也是一个值得关注的问题,可以使用wait、notify、join等方法来实现线程间的协作。 总之,Java多线程的使用可以提高程序的并发性和响应性,但需要注意线程安全、资源消耗以及线程协调和通信等问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值