多线程基础篇

  • 基本概念 (程序,进程,线程)
  • 线程的创建和使用
  • 线程的生命周期
  • 线程的同步
  • 线程的通信
  • JDK5.0新增线程创建方式
程序 (program):为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
进程 (process):程序的一次执行过程,或是正在运行的一个程序。
是一个动态的过程:有它自身的产生、存在和消亡的过程。——生命周期。
·如:运行中的 QQ,运行中的 MP3 播放器程序是静态的,进程是动态的。
·进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区
域
线程 (thread):进程可进一步细化为线程,是一个程序内部的一条执
行路径。
·若一个进程同一时间并行执行多个线程,就是支持多线程的。
·线程是调度和执行的单位,每个线程拥有独立的运行栈和程序计数器 (pc),
线程切换的开销小。
·一个进程中的多个线程共享相同的内存单元 / 内存地址空间—》它们从同
一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、
高效。但多个线程操作共享的系统资源可能就会带来安全的隐患。
class MyThread extends Thread {

    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName()+i);
            }
        }

    }

}

public class ThreadTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();//通过调用此对象的start方法:1.启动当前线程,2调用当前线程的run()
        MyThread myThread2 = new MyThread();
        myThread2.start();
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(i + "#####");
            }
        }
    }

}

class MThread implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i % 2 ==0){
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
        }
    }
}
public class ThreadTest1 {
    public static void main(String[] args) {
        MThread mThread = new MThread();
        new Thread(mThread).start();
    }

}
/**
 * @deprecated
 * 测试Thread中常用的方法:
 * 1.start():启动当前线程:调用当前线程的run();
 * 2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
 * 3.currentThread():静态方法,返回执行当前代码的线程
 * 4.getName():获取当前线程的名字
 * 5.setName():设置当前线程的名字
 * 6.yield():释放当前cpu的执行权
 * 7.join():线程插队,谁调用谁插队,在线程a中调用b的join,a进入阻塞状态,b获取执行权,
 * b执行完以后,a才结束阻塞状态,等待cpu分配资源
 * 8.stop():强制结束声明周期,不推荐使用
 * 9.sleep(long millitime):让当前线程睡眠指定时间,指定时间内,当前线程为阻塞状态
 * 10.isAlive():判断当前线程是否还存活
 *
 *
 * 线程的优先级:
 * 1.

 * MAX_PRIORITY :10
 * MIN_PRIORITY :1
 * NORM_PRIORITY :5
 * 2.如何获取和设置线程的优先级
 * getPriority()和setPriority()
 * 说明:高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下被执行。
 * 并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。
 *
 *
 * @author zx
 * @create 2022-08-14 21:09
 */

开发中:优先选择:实现Runnable接口的方式原因:

实现的方式没有类的单继承性的局限性

实现的方式更适合来处理多个线程有共享数据的情况。

联系: public class Thread implements Runnable

相同点:两种方式都需要重写run( ),将线程要执行的逻辑声明在run( )中。

进程可以细化为多个线程。

每个线程,拥有自己独立的:栈、程序计数器

多个线程,共享同一个进程中的结构:方法区、堆。

1、新建状态(New):新创建了一个线程对象。 
2、就绪状态(Runnable):也叫可运行状态。线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。 
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。 
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种: 
①等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。 
②同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。 
③其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
方法一:同步代码块
      synchronized(同步监视器){
      //需要被同步的代码
      }
      说明:
      1操作共享数据的代码,即为需要被同步的代码
      2共享数据:多个线程共同操作的变量
      3同步监视器,俗称:锁。任何一个类的对象,都可以充当锁
      要求:多个线程必须要共用同一把锁

方法二:同步方法

    同步的方式,解决了线程的安全问题。---好处
    操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。---局限性

package com.zx.java1;

/**
 * @author zx
 * @create 2022-08-15 18:11
 */
public class BankTest {
}

class Bank {
    public Bank() {

    }

    private static Bank instance = null;

    public static Bank getInstance() {
        //方法一:
        /*synchronized (Bank.class) {
            if (instance == null) {
                instance = new Bank();
            }
        }
        return instance;*/
        //方法二:效率更高
        if (instance == null) {
            synchronized (Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }
            }
        }
        return instance;
    }

}
synchronized 和 lock的异同
相同:二者都可以解决线程安全问题
不同:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
    Lock需要手动的启动同步(Lock()),同时结束同步也需要手动的实现(unlock())
如何解决线程安全问题?有几种方式
有三种,分别是synchronized修饰的方法,synchronized的代码块,还有JDK5.0之后的lock的使用
线程通信的例子:使用两个线程打印1-100。线程1,线程2 交替打印
 * wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
 * notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个wait,就换醒优先级高的那个线程
 * notifyAll(): 一旦执行此方法,就会唤醒所有被wait()的线程

 class Number implements Runnable{
    private int number = 1;
    @Override
    public void run() {
        while (true){
            synchronized (this) {
                //唤醒被wait的线程
                notify();
                if (number
sleep() 和 wait() 有什么区别?

sleep就是暂停当前线程一段时间,把cpu让给其他线程使用,到时后会自动恢复。调用sleep不会释放对象锁。 wait方法导致本线程放弃对象锁,进入等待,只有等到本对象的notify方法(或notifyAll)后本线程才进入就绪状态,等待执行
wait()必须使用在同步代码块或同步方法中,sleep()可以在任何需要的场景下调用
package com.zx.java2;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * &#x5982;&#x4F55;&#x7406;&#x89E3;&#x5B9E;&#x73B0;Callable&#x63A5;&#x53E3;&#x7684;&#x65B9;&#x5F0F;&#x521B;&#x5EFA;&#x591A;&#x7EBF;&#x7A0B;&#x6BD4;&#x5B9E;&#x73B0;Runnable&#x63A5;&#x53E3;&#x521B;&#x5EFA;&#x591A;&#x7EBF;&#x7A0B;&#x65B9;&#x5F0F;&#x5F3A;&#x5927;?

 * 1. calL()&#x53EF;&#x4EE5;&#x6709;&#x8FD4;&#x56DE;&#x503C;&#x7684;&#x3002;
 * 2. caLL()&#x53EF;&#x4EE5;&#x629B;&#x51FA;&#x5F02;&#x5E38;&#xFF0C;&#x88AB;&#x5916;&#x9762;&#x7684;&#x64CD;&#x4F5C;&#x6355;&#x83B7;&#xFF0C;&#x83B7;&#x53D6;&#x5F02;&#x5E38;&#x7684;&#x4FE1;&#x606F;
 * 3. calLable&#x662F;&#x652F;&#x6301;&#x6CDB;&#x578B;&#x7684;
 * @author zx
 * @create 2022-08-16 17:32
 *
 */
//1.&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5B9E;&#x73B0;Callable&#x7684;&#x5B9E;&#x73B0;&#x7C7B;
class NewThread implements Callable {

    @Override
    //2.&#x5B9E;&#x73B0;caLl&#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x6B64;&#x7EBF;&#x7A0B;&#x9700;&#x8981;&#x6267;&#x884C;&#x7684;&#x64CD;&#x4F5C;&#x58F0;&#x660E;&#x5728;call()&#x4E2D;
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 2="=" 100; i++) { if (i % 0){ system.out.println(i); sum +="i;" } return sum; public class threadnewtest static void main(string[] args) 3.创建callable接口实现类的对象 newthread newthread(); 4.将此callable接口实现类的对象作为传递到futuretask构造器中,创建futuretask的对象 futuretask futuretask(newthread); 5.将futuretask的对象作为参数传递到thread类的构造器中,创建thread对象,并stdrt() new thread(futuretask).start(); try 6.获取callable中dll方法的返回值 get()返回值为futuretask构造器参数callable实现类重写的call()的返回值 object system.out.println(sum); catch (interruptedexception e) e.printstacktrace(); (executionexception < code></=>
package com.zx.java2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 创建线程的方式4:使用线程池
 * 好处:降低资源消耗(重复利用线程池中线程,不需要每次都创建)
 * 便于线程管理
 * 提高响应速度(减少了创建新线程的时间)
 *
 * @author zx
 * @create 2022-08-16 19:01
 */

class NumberThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0){
                System.out.println(Thread.currentThread().getName() +"----" + i);
            }
        }
    }
}

class NumberThread2 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0){
                System.out.println(Thread.currentThread().getName() +"----" + i);
            }
        }
    }
}
public class ThreadPool {
    public static void main(String[] args) {
        //提供指定线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);

        //2.执行指定的线程的操作。需要提供实现Runnable接口或callable接口实现类的对象
        service.execute(new NumberThread());//适用于Runnable
        service.execute(new NumberThread2());
        //service.submit();适用于Callable

        //3.关闭连接池
        service.shutdown();

    }
}

Original: https://www.cnblogs.com/zxyyds/p/16592718.html
Author: 帆再小也能远航
Title: 多线程基础篇

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574567/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Fatal error: Call to undefined function session_start()

    在FreeBSD主机上执行PHP页面报以下错误,Fatal error: Call to undefined function session_start() ,应该是在没有安装扩…

    Java 2023年5月30日
    080
  • elasticsearch

    一、什么是Elasticsearch? Lucene是一套用于 全文检索和 搜寻的 开源程序库,由Apache软件基金会支持和提供 Lucene提供了一个简单却强大的应用程序接口(…

    Java 2023年6月9日
    0142
  • 缓存雪崩问题,缓存穿透问题及解决思路

    1.缓存雪崩 缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。 解决方案: 给不同的Key的TTL添加随机值 利用Red…

    Java 2023年6月9日
    069
  • Redis+Lua实现简易的秒杀抢购

    1 商品抢购 主要逻辑是:减库存,记录抢购成功的用户 @RestController public class DemoController { @Resource private…

    Java 2023年6月7日
    085
  • wince程序 中使用Listview显示图标问题 (C#)

    思路: 1、窗体控件:lstaqgl 【Listview控件名称】 imageList1【ImageList控件】 图片路径添加到—imageList1——Listview显示图片…

    Java 2023年5月29日
    098
  • 一个终端工具竟然有AI功能?使用了1天我立马把其他终端全卸载了!太香了!

    前言 平常工作需要频繁使用终端工具,有一个好的命令行终端工具是非常重要的。 尤其是使用mac的小伙伴,估计不少人都觉得iterm2才是最好的终端工具。 其实起初我也是这么觉得的,但…

    Java 2023年6月8日
    078
  • PHP 实现微信红包拆分算法

    php;gutter:true; handle(); * print_r($res); * * @author Flc * @see http://flc.ren | http:/…

    Java 2023年6月7日
    061
  • 单例模式详解

    单例模式详解 1.1单例模式概述 单例模式(Singleton Pattern)指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点,属于创建型设计模式。 1.2单例模…

    Java 2023年6月7日
    088
  • 123456789 给一个字符串随机添加 “-”,“+” 和为100

    面试题 123456789 给一个字符串随机添加 “-“,”+”生成一个公式计算和为100; import java.util.Ra…

    Java 2023年6月7日
    070
  • Spring源码 Gradle编译Spring源码

    准备工作 原本以为不就是编译个源码么,想不到还是折腾了挺久的,记录一下吧。 1.IDEA版本 2017.1.2 2.gradle版本 4.5 3.Spring framework …

    Java 2023年5月30日
    090
  • PyCharm正版(专业版)购买的话多少钱一年?

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年5月29日
    094
  • 从.NET和Java之争谈IT这个行业

    开篇我得表名自己的立场:.NET JAVA同时使用者,但更加偏爱.NET.原因很简单 1.NET语言更具开放性,从开源协议和规范可以看出; 2.语言更具优势严谨; 3.开发工具VS…

    Java 2023年5月29日
    070
  • 【Redis】Redis Cluster-集群数据迁移

    Redis通过对KEY计算hash,将KEY映射到slot,集群中每个节点负责一部分slot的方式管理数据,slot最大个数为16384。在集群节点对应的结构体变量clusterN…

    Java 2023年6月8日
    084
  • 二分查找法

    使用二分查找的条件: 有序数组 需求 在数组{1,2,3,4,5,6,7,8,9,10}中,查找某个元素的位置 实现步骤 定义两个变量,表示要查找的范围。默认min = 0 ,ma…

    Java 2023年6月14日
    062
  • zookeeper简介及基操

    cpp;gutter:true; zk的安装: 1. 下载zk.tar.gz安装包,并解压至/usr/local/devInstall 2. 在zk的目录下新建文件夹data 3….

    Java 2023年6月8日
    072
  • 服务调用过程

    前言 本文基于Dubbo2.6.x版本,中文注释版源码已上传github:xiaoguyu/dubbo 源码分析均基于官方Demo,路径:dubbo/dubbo-demo 如果没有…

    Java 2023年6月16日
    073
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球