iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java学习随记之多线程编程
  • 378
分享到

Java学习随记之多线程编程

2024-04-02 19:04:59 378人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

Process和Thread 程序是指令和数据的有序集合, 本身没有运行的含义,是一个静态的概念。 进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位 一个进程中

Process和Thread

程序是指令和数据的有序集合, 本身没有运行的含义,是一个静态的概念。

进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位

一个进程中可以包含若干个线程,线程是CPU调度和执行的单位

线程创建

三种创建方法

继承Thread类


//创建线程方法一:继承Thread类,重写run() 方法,调用start开启主线程
public class TestThread01 extends Thread{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 2000; i++) {
            System.out.println("我在看代码-----" + i);
        }
    }
    public static void main(String[] args) {
        //main线程,主线程
        //创建一个线程对象
        TestThread01 testThread01 = new TestThread01();
        //调用start方法开启多线程,子线程调用run方法,主线程和子线程并行交替执行
        testThread01.start();
        //testThread01.run(); //主线程调用run方法,只有主线程一条执行路径

        for (int i = 0; i < 2000; i++) {
            System.out.println("Im" + i);
        }
    }
}

总结:注意,线程开启不一定立即执行,由CPU调度处理

  • 子类继承Thread类,具备多线程能力、
  • 启动线程:子类对象.start()
  • 不推荐使用:避免OOP单继承局限性

小练习


import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;

//练习Thread,实现多线程同步下载图片
public class TestThread02 extends Thread{
    private String url;
    private String name;

    public TestThread02(String url, String name) {
        this.url = url;
        this.name = name;
    }
    @Override
    public void run() {
        WEBDownloader webDownloader = new WebDownloader();
        webDownloader.downloadr(url, name);
        System.out.println("下载了:" + name);

    }

    public static void main(String[] args) {
        TestThread02 t1 = new TestThread02("/file/imgs/upload/202211/12/2225u1rbm5f.jpg?…3DlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "1.png");
        TestThread02 t2 = new TestThread02("/file/imgs/upload/202211/12/v54grbnrbo1.jpg", "2.png");
        TestThread02 t3 = new TestThread02("/file/imgs/upload/202211/12/2225u1rbm5f.jpg?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "3.png");

        t1.start();
        t2.start();
        t3.start();
    }
}
//下载器
class WebDownloader{
    public void downloadr(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常, downloader出现问题");
        }
    }
}

实现Runnable


//创建线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread03 implements Runnable{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 2000; i++) {
            System.out.println("我在看代码-----" + i);
        }
    }

    public static void main(String[] args) {
        //创建runnable 接口的实现类对象
        TestThread03 testThread03 = new TestThread03();

        //创建线程对象,通过线程对象来开启线程,代理
//        Thread thread = new Thread(testThread03);
//        thread.start();
        new Thread(testThread03).start();
        

        for (int i = 0; i < 1000; i++) {
            System.out.println("Im" + i);
        }
    }
}

总结:

  • 实现接口Runnable具备多线程能力
  • 启动线程:传入目标对象+Thread对象.start()
  • 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被线程使用

出现的问题

多个线程操作操作同一个资源的情况下,线程不安全,数据紊乱


//多个线程同时操作同一个对象
//买火车票的例子

//发现问题:多个线程操作操作同一个资源的情况下,线程不安全,数据紊乱
public class TestThread04 implements Runnable {

    //票数
    private int ticketNums = 10;

    @Override
    public void run() {
        while (true) {
            if (ticketNums <= 0) {
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums-- + "票");
        }
    }

    public static void main(String[] args) {
        TestThread04 testThread04 = new TestThread04();

        new Thread(testThread04, "老师").start();
        new Thread(testThread04, "黄牛").start();
        new Thread(testThread04, "小明").start();
    }
}

实现Callable接口

1、实现Callable接口,需要返回值类型

2、重写call方法,需要抛出异常

3、创建目标对象

4、创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(3);(使用了线程池)

5、提交执行:Future r1 = ser.submit(t1);

6、获取结果:boolean res1 = r1.get();

7、关闭服务:ser.shutdown();


import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

//线程创建方式三:实现Callable接口(了解即可)
// 实现Callable接口
public class TestCallable implements Callable<Boolean> {

    private String url;
    private String name;

    public TestCallable(String url, String name) {
        this.url = url;
        this.name = name;
    }
    @Override
    public Boolean call() {
        WebDownloader1 webDownloader1 = new WebDownloader1();
        webDownloader1.downloadr(url, name);
        System.out.println("下载了:" + name);
        return true;

    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1 = new TestCallable("/file/imgs/upload/202211/12/2225u1rbm5f.jpg?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "1.png");
        TestCallable t2 = new TestCallable("/file/imgs/upload/202211/12/v54grbnrbo1.jpg", "2.png");
        TestCallable t3 = new TestCallable("/file/imgs/upload/202211/12/2225u1rbm5f.jpg?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "3.png");

        //1、创建执行服务()    线程池
        ExecutorService ser = Executors.newFixedThreadPool(3);
        //2、提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        //3、获取结果
        boolean res1 = r1.get();
        boolean res2 = r2.get();
        boolean res3 = r3.get();

        //4、关闭服务
        ser.shutdown();

    }

}
//下载器
class WebDownloader1{
    public void downloadr(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常, downloader出现问题");
        }
    }
}

Lambda表达式

为什么要使用lamba表达式

避免匿名内部类定义过多

可以让代码看起来更整洁

去掉了一堆没有意义的代码,只留下核心逻辑

示例




public class TestLambda01 {

    //3、静态内部类
    static class Like2 implements ILike {

        @Override
        public void lambda() {
            System.out.println("I like lambda2");
        }
    }

    public static void main(String[] args) {
        ILike like = new Like();
        like.lambda();

        like = new Like2();
        like.lambda();

        //4、局部内部类
        class Like3 implements ILike {
            @Override
            public void lambda() {
                System.out.println("I like lambda3");
            }
        }
        like = new Like3();
        like.lambda();

        //5、匿名内部类
        like = new ILike() {
            @Override
            public void lambda() {
                System.out.println("I like lambda4");
            }
        };
        like.lambda();

        //6、用lambda简化 jdk1.8特性
        like = ()->{
            System.out.println("I like lambda5");
        };
        like.lambda();

    }
}

//1、定义一个函数式接口----必须有
interface ILike {
    void lambda();
}

//2、实现类
class Like implements ILike {

    @Override
    public void lambda() {
        System.out.println("I like lambda");
    }
}

对于lambda表达式的简化


public class TestLambda02 {

    public static void main(String[] args) {
        //标准格式
//        ILove love = (int a)->{
//                System.out.println("I Love you " + a);
//        };
        //简化1   去掉参数类型,多个不同类型的参数也可以直接去掉
        ILove love = (a) -> {
            System.out.println("I love you " + a);
        };
        //简化2   去掉括号    -->仅单参数
        love = a->{
            System.out.println("I love you " + a);
        };
        //简化3   去掉花括号  --> 仅lambda表达式有一行时才可
        love = a -> System.out.println("I love you " + a);
        love.love(520);
        //使用lambda表达式仅适用于函数式接口(接口里只有一个函数接口)
    }
}

interface ILove {
    void love(int a);
}

静态代理


//静态代理模式:
//真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色
//好处:
    //代理对象可以做很多真实对象做不了的事
    //真实对象专注做自己的事
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();

        new Thread(	() -> System.out.println("I Love You")).start();
        new WeddinGCompany(new You()). HappyMarry();
        
        
    }
}

interface Marry {
    void HappyMarry();

}
// 真实对象
class You implements Marry {
    @Override
    public void HappyMarry() {
        System.out.println("Happy");
    }
}

// 代理
class WeddingCompany implements Marry {
    //代理谁->真实目标角色
    private Marry target;

    public WeddingCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry();
        after();
    }

    private void after() {
        System.out.println("后");
    }

    private void before() {
        System.out.println("前");
    }
}

线程状态

方法 说明
setPriority(int newPriority) 更改线程的优先级
static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠
void join() 等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
void interrupt() 中断线程,别用这个方式
boolean isAlive() 测试线程是否处于某个活动状态

线程终止

  • 不推荐使用JDK提供的stop()、destroy()方法
  • 推荐线程自己停止下来
  • 建议使用一个标志位进行终止变量,当flag = false,则终止线程运行

//测试stop
//1、建议线程正常停止---->利用次数,不建议死循环
//2、建议使用标志位----->设置一个标志位
//3、不要使用stop或者destroy等过时或者jdk不推荐的方法
public class TestStop implements Runnable {
    //1、设置一个标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run-----thread" + i++);
        }
    }
    //2、设置一个公开的方法停止线程,转换标志位
    public void stop() {
        this.flag = false;
    }
    public static void main(String[] args) throws InterruptedException {
        TestStop testStop = new TestStop();

        new Thread(testStop).start();

        for (int i = 0; i < 1000; i++) {
            Thread.sleep(1);
            if (i == 900) {
                testStop.stop();

                System.out.println("Stop");
                break;
            }
        }
    }
}

线程休眠

  • sleep(时间) 指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptedException
  • sleep时间达到后进入就绪状态
  • sleep可以模拟网络延时(放大问题的发生性),倒计时等
  • 每一个对象都有一个,sleep不会释放锁

import java.text.SimpleDateFORMat;
import java.util.Date;

public class TestSleep2 {
    //模拟倒计时
    public static void tenDown(){
        int num = 10;
        while (num > 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(num--);
        }
    }

    public static void main(String[] args) {
        //打印当前时间
        Date startTime = new Date(System.currentTimeMillis());  //获取时间

        while (true) {
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:MM:SS").format(startTime));
                startTime = new Date(System.currentTimeMillis());//更新时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程礼让

  • 礼让线程,让当前正在执行的线程停止,但不阻塞
  • 让线程从运行态转换为就绪态
  • 让CPU重新进行调度,礼让不一定成功,看CPU心情

public class TestYield {
    public static void main(String[] args) {
        Myyield myyield = new Myyield();

        new Thread(myyield, "A").start();
        new Thread(myyield, "B").start();
    }
}

class Myyield implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() +  "线程开始");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() +  "线程停止");
    }
}

JOIN

JOIN合并线程,待此线程执行完后,再执行其他线程,其他线程阻塞

可以想象成插队


//插队
public class TestJoin implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 100; i++) {
            System.out.println("VIP" + i);
        }
    }

    public static void main(String[] args) {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        for (int i = 0; i < 1000; i++) {
            if (i == 200) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main" + i);
        }
    }
}

线程状态观测

线程状态。线程可以处于以下状态之一:

NEW

尚未启动的线程处于此状态。

RUNNABLE

在Java虚拟机中执行的线程处于此状态。

BLOCKED

被阻塞等待监视器锁定的线程处于此状态。

WAITING

无限期等待另一个线程执行特定操作的线程处于此状态。

TIMED_WAITING

正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。

TERMINATED

已退出的线程处于此状态。


//观测测试线程的状态
public class TestStatus {

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i);
            }
            System.out.println("/////////////");
        });

        //观察状态
        Thread.State state = thread.getState();
        System.out.println(state);

        //观察启动后
        thread.start();

        state = thread.getState();
        System.out.println(state);

        while (state != Thread.State.TERMINATED) { //只要线程不终止,就一直输出状态
            try {
                Thread.sleep(100);
                state = thread.getState();
                System.out.println(state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }


    }
}

线程的优先级

Java提供一个线程调度器来监控程序中启动后进入就绪态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行

线程的优先级用数字表示,范围从1~10

  • Thread.MIN_PRIORITY = 1;
  • Thread.MAX_PRIORITY = 10;
  • Thread.NORM_PRIORITY = 5;

使用以下方法改变或者获取优先级

  • getPriority
  • setPriority

优先级低只是意味着获得调度的概率低,并不是优先级低的就不会调用了,这都是看CPU的调度


public class TestPriority extends Thread {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + "====>" + Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();

        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        Thread t5 = new Thread(myPriority);

        t1.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
        t5.setPriority(8);
        t5.start();
    }
}

class MyPriority implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "====>" + Thread.currentThread().getPriority());
    }
}

守护(daemon)线程

  • 线程分为用户线程和守护线程
  • JVM虚拟机必须确保用户线程执行完毕
  • JVM虚拟机不用等待守护线程执行完毕

public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认式false表示是用户线程,正常的线程是用户线程

        thread.start();

        new Thread(you).start();
    }

}

//上帝
class God implements Runnable {

    @Override
    public void run() {
        while (true) {
            System.out.println("god");
        }
    }
}
//你
class You implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("Happy");
        }
        System.out.println("Goodbye world");
    }
}

同步(synchronized)

synchronized

由于我们可以提出private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块。


public synchronized void method(){}

synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行

缺陷:若将一个大的方法声明为synchronized,将会影响效率

同步方法

synchronized方法控制对成员变量或者类属性对象的访问,每个对象对应一把锁。写法如下:


public synchronized void test(){
    //。。。。
}
  1. 如果修饰的是具体对象:锁的是对象
  2. 如果修饰的是成员方法:锁的是this
  3. 如果修饰的是静态方法:锁的就是这个对象.class

每个synchronized方法都必须获得该方法的对象的锁才能执行,否则所属的这个线程阻塞,方法一旦执行,就独占该锁,直到该方法返回时,锁释放。

原程序:


public class Checkout {

    public static void main(String[] args) {
        Account account = new Account(200000, "礼金");
        Drawing you = new Drawing(account, 80000, "你");
        Drawing wife = new Drawing(account, 140000, "your wife");
        you.start();
        wife.start();
    }
}

class Account {
    int money;
    String name;

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}

class Drawing extends Thread {
    Account account;
    int outMoney;
    int outTotal;

    public Drawing(Account account, int outMoney, String name) {
        super(name);
        this.account = account;
        this.outMoney = outMoney;
    }

    @Override
    public void run() {
        test();
    }

    public void test() {
        if (account.money < outMoney) {
            System.out.println("余额不足");
            return;
        }
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money -= outMoney;
        outTotal += outMoney;
        System.out.println(this.getName() + "-----账户余额为:" + account.money);
        System.out.println(this.getName() + "-----总共取到了:" + outTotal);
    }
}

显然,上面的代码会出现负数,但是我们不希望它出现负数。

同步方法的写法代码,以上面代码为例,直接在提款机的操作,把run方法或者里面的内容提出来变成test,加上synchronized修饰:


@Override
public void run(){
}
public synchronized void test(){
}

但是这样仍会发现出现负数,锁定失败。

分析:

我们认为在test方法里进行的对象修改,所以把他锁上就好了,但是,对于这个类,这个提款机来说,test时成员方法,因此锁的对象实际上是this,也就是提款机(Drawing)。

但是我们的初衷,希望线程锁定的资源是Account对象,而不是提款机对象。

同步块

除了方法,synchronized还可以修饰块,叫做同步块。

synchronized修饰同步块的方式是:

synchonized (obj){ }

其中的obj可以是任何对象,但是用到它,肯定是设置为那个共享资源,这个obj被称为同步监视器。同步监视器的作用就是,判断这个监视器是否被锁定(是否能访问),从而决定其是否能执行其中的代码。

Java的花括号中内容有一下几种:

  1. 方法里面的块:局部快。解决变量作用域的问题,快速释放内存(比如方法里面再有个for循环,里面的变量)
  2. 类层的块:构造块。初始化信息,和构造方法是一样的
  3. 类层的静态块:静态构造块。最早加载,不是对象的信息,而是类的信息;
  4. 方法里面的同步块:监视对象。

第四种就是我们目前学习的同步块。

注意:如果是同步方法里,没必要指定同步监视器,因为同步方法的监视器已经是this或者.class

使用同步块对提款机问题进行修改:


public void test(){
    synchronized(account){
        
    }
}

也就是加上对account的监视器,锁住了这个对象 ,这样运行结果就正确了。

这种做法的效率不高,因为虽然对account上了锁,但是每一次都要把整个流程走一遍,方法体内的内容是很多的,另外,每次加锁与否,都是对性能的消耗,进入之后再出来,哪怕什么都不做,也是消耗。

其实,我们可以在加锁的外面再加一重判断,那么之后就没有必要再进行锁的过程了。


public void test(){
    if (account.money == 0){
        return;
    }
    synchronized(account){
    }
}

就是这样的代码,在并发量很高的时候,往往可以大大提高效率。

问题

synchronized块太小,可能锁不住,安全性又太低了,锁的方法太大,又会降低效率,所以要很注意控制范围 

以上就是Java学习随记之多线程编程的详细内容,更多关于Java多线程的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java学习随记之多线程编程

本文链接: https://www.lsjlt.com/news/159817.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java学习随记之多线程编程
    Process和Thread 程序是指令和数据的有序集合, 本身没有运行的含义,是一个静态的概念。 进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位 一个进程中...
    99+
    2024-04-02
  • Java多线程学习笔记
    目录多任务、多线程程序、进程、线程学着看jdk文档线程的创建1.继承Thread类2.实现Runable接口理解并发的场景龟兔赛跑场景实现callable接口理解函数式接口理解线程的...
    99+
    2024-04-02
  • 学习java多线程
    目录介绍为什么需要多线程线程状态转换线程使用方式继承 Thread 类实现 Runnable 接口实现 Callable 接口同步代码---Runnable接口方式同步方法--Run...
    99+
    2024-04-02
  • Python学习笔记之线程
    目录1.自定义进程2.进程与线程3.多线程4.Thread类方法5.多线程与多进程小Case6.Thread 的生命周期7.自定义线程8.线程共享数据与GIL(全局解释器锁)9.GI...
    99+
    2024-04-02
  • JAVA编程学习笔记
    常用代码、特定函数、复杂概念、特定功能……在学习编程的过程中你会记录下哪些内容?快来分享你的笔记,一起切磋进步吧! 一、常用代码 在java编程中常用需要储备的就是工具类。包括封装的时间工具类。htt...
    99+
    2023-09-03
    java 学习 笔记
  • Java多线程之锁的强化学习
    目录Java8锁SynchronizedReentrantLockAQSvolatile自旋锁 ,自旋锁的其他种类CAS 自旋锁CAS的实现原理首先强调一点:Java多线程的锁都是基...
    99+
    2023-02-26
    Java多线程 锁 Java多线程 Java 锁
  • Java多线程之锁学习(增强版)
    目录阻塞锁非阻塞锁锁的四种状态无锁状态偏向锁轻量级锁重量级锁可重入锁自旋锁读写锁互斥锁悲观锁乐观锁公平锁非公平锁显示锁和内置锁轮询锁和定时锁对象锁和类锁锁粗化锁消除信号量独享锁共享锁...
    99+
    2023-02-26
    Java多线程 锁 Java多线程 Java 锁
  • Python学习记录-多进程和多线程
    [TOC] 1. 进程和线程 进程 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。广义定义:进程是一个具有一定独立功能的程序关于某...
    99+
    2023-01-31
    多线程 进程 Python
  • java多线程编程之InheritableThreadLocal
    InheritableThreadLocal的作用: 当我们需要在子线程中使用父线程中的值得时候我们就可以像使用ThreadLocal那样来使用InheritableThreadLocal了。 首先我们来看一下InheritableThre...
    99+
    2023-05-31
    java 多线程 inheritablethreadlocal
  • Java多线程Thread基础学习
    目录1. 创建线程   1.1 通过构造函数:public Thread(Runnable target, String name){}  或:publ...
    99+
    2023-05-17
    Java多线程 Java 多线程Thread
  • Java 多线程学习总结3
    在上一篇中,我们当然希望a++,b++执行完之后,show方法再来show.我们需要的是“原子”动作,一次性地把a++,b++不间断地执行。在java中是利用“互斥”的方法,互斥谁呢?互斥的是相同对象的加锁代码。如果我们把第一篇的SomeB...
    99+
    2023-01-31
    多线程 Java
  • Java线程学习之并发编程知识点有哪些
    本文小编为大家详细介绍“Java线程学习之并发编程知识点有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java线程学习之并发编程知识点有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、JMM 基础-...
    99+
    2023-07-02
  • Java学习笔记之面向对象编程精解
    目录包继承super 关键字finalprotected关键字组合多态抽象类接口面向对象编程(包、继承、组合、多态 、抽象类、接口) 包 包其实就是类的集合,其本质上其实就是一个文件...
    99+
    2024-04-02
  • python多线程学习
    python多线程学习:python中的线程使用的两种方式:函数或者用类来包装线程对象。1、函数式:调用thread模块中start_new_thread()函数来产生新线程。#!/usr/bin/env python #coding:ut...
    99+
    2023-01-31
    多线程 python
  • C#多线程学习之基础入门
    目录同步方式异步多线程方式异步多线程优化异步回调异步信号量异步多线程返回值异步多线程返回值回调线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进...
    99+
    2024-04-02
  • 理解Java多线程之并发编程
    目录1 多线程的使用场景2 多线程的缺点2.1 上下文切换的开销(1)上下文切换的开销(2)如何减少上下文切换2.2 多线程中的数据一致性问题(1)线程中访问外部数据的过程(2)线程...
    99+
    2023-02-02
    Java并发编程 java并发编程实战 java并发编程的艺术
  • Java 多线程编程
    Java 多线程编程   目录 Java 多线程编程 一个线程的生命周 线程的优先级 创建一个线程 通过实现Runnable接口来创建线程 实例 通过继承Thread来创建线程 实例 Thread 方法 实例   线程的几个主要概念: 多线...
    99+
    2023-10-20
    python 开发语言
  • Java进阶必备之多线程编程
    目录一、图示二、多线程编程三、线程的工作过程四、创建多线程一、图示 二、多线程编程 何为多线程,通俗的讲就是让你的代码同时干好几件事。 而我们的一个代码文件或者一个项目就是一个进程...
    99+
    2024-04-02
  • Python多线程学习 setDae
    (2)setDaemon方法: # -*- coding: utf-8 -*- import threading import time class myThread(threading.Thread):     def __init...
    99+
    2023-01-31
    多线程 Python setDae
  • Java学习之线程同步与线程间通信详解
    目录线程同步的概念同步代码块同步方法线程组线程组的相关方法线程组对象的基本应用线程间的通信线程通信简单应用线程同步的概念 由于同一个进程的多个线程共享同一块存储空间,在带来方便的同时...
    99+
    2022-12-27
    Java线程同步 Java线程通信 Java线程
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作