对于多线程知识的总结(超详细)

大家好,我是忘鱼。这期干货满满,多线程从浅到深的讲解。


目录

一、多线程的三种建立方式。

二、Thread常用方法。

1,Thread.currentThread().getName();

2,Thread.sleep();

三、线程安全问题,原因与解决方案。

1、模拟线程安全问题案例:取款。

2、解决方案:三种,同步代码块,同步方法,同步锁。

四、线程池(很重要的知识)

1,创建线程池

方法一:ExecutorServive

方法二:Executors

五、线程池处理Runnable与Callable任务。

1,简单的案例处理

六、定时器

1、Timer实现

2、scheduledExecutorService实现

七、多线程并发并行,与生命周期。

1、并发就是。

2、并行就是。

3、生命周期

八,总结


一、多线程的三种建立方式。

//建立多线程方法1
public class ThreadDemo1 {
    public static void main(String[] args) {
      Thread t=new Mythread();
      t.start();
        for (int i = 0; i < 5; i++) {

            System.out.println("主线程执行了"+i);
        }


    }
 static class Mythread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {

                System.out.println("子线程执行了"+i);
            }
        }
    }
}
//建立方式二,
public class ThreadDemo2 {
    public static void main(String[] args) {
       Runnable th=new MyRunnable();
       Thread t=new Thread(th);
        t.start();
        Runnable th2=new MyRunnable();
        Thread t2=new Thread(th2);
        t2.start();
//    两个线程近似看做同时执行。
        for (int i = 0; i < 5; i++) {

            System.out.println("主线程执行了"+i);
        }
    }
 static class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {

                System.out.println(Thread.currentThread().getName()+"子线程执行了"+i+"---------"+System.nanoTime());
            }
        }
    }
}
//还是方式2,多了匿名类部类。
//建立多线程方法2匿名类部类
public class ThreadDemo02 {
    public static void main(String[] args) {
Runnable th=new Runnable() {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程执行了"+i);
        }
    }
};
Thread t=new Thread(th);
t.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行了"+i);
        }
    }

}
//建立方式3,算个例题吧
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadDemo3 {
    public static void main(String[] args) {
        Callable<String> call=new MyCallable(100);
        FutureTask<String> task = new FutureTask<>(call);
        Thread t = new Thread(task);
        t.start();
        Callable<String> call2=new MyCallable(200);
        FutureTask<String> task2 = new FutureTask<>(call2);
        Thread t2 = new Thread(task2);
        t2.start();
//两个子线程同时执行,主线程

        try {
            String t1=task.get();
            System.out.println("第一个线程结果"+t1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            String t12=task2.get();
            System.out.println("第二个线程结果"+t12);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    static class   MyCallable implements Callable<String>{
        private int  n;

        public MyCallable (int n) {
            this.n = n;
        }

        int sum=0;
        @Override
        public String call() throws Exception {
            for (int i = 1; i <=n ; i++) {
                sum+=i;
            }
            return "子线程执行结果"+sum;
        }
    }
}

二、Thread常用方法。

1,Thread.currentThread().getName();

     获取当前线程名字,与那个获取当前对象this道理一样。

2,Thread.sleep();

     执行到此处休眠,括号内是毫秒。

三、线程安全问题,原因与解决方案。

1、模拟线程安全问题案例:取款。

2、解决方案:三种,同步代码块,同步方法,同步锁。

         案例、线程出现安全问题,是由于多个线程同时处理同一资源,导致出错如:给个案例谈谈。比如说小兰与小花共同有一个账户,里面有10万元,她们同时取钱出现了小兰与小花都取了10万,卡里所剩-10万。

当然解决方案有三种,代码块里面会显示。看代码

public class ThreadDemo {
    public static void main(String[] args) {
        Account acc=new Account("1298323",100000.0);
        new DrawThread(acc,"小兰").start();
        new DrawThread(acc,"小花").start();

    }
}



public class DrawThread extends Thread{
    private Account acc;
    public DrawThread(Account acc,String name){
        super(name);
        this.acc=acc;
    }
    @Override
    public void run() {
//        取钱方法
acc.drawMoney(100000);
    }
}



import javax.sound.sampled.Line;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Account {
    private String cardid;
    private double money;
private final Lock lock=new ReentrantLock();
    public Account() {
    }
    public void drawMoney(double money) {
        String name=Thread.currentThread().getName();
            if(this.money>=money){
                System.out.println("恭喜"+name+"取走了钱:"+money);
                this.money-=money;
                System.out.println("所剩余额:"+this.money);
            }else {
                System.out.println("余额不足");
            }
        }
//解决方案一
    /*public void drawMoney(double money) {
        String name=Thread.currentThread().getName();
        synchronized (this) {
            if(this.money>=money){
                System.out.println("恭喜"+name+"取走了钱:"+money);
                this.money-=money;
                System.out.println("所剩余额:"+this.money);
            }else {
                System.out.println("余额不足");
            }
        }
    }*/
//    解决方案2
    /*public synchronized void drawMoney(double money) {
        String name=Thread.currentThread().getName();

            if(this.money>=money){
                System.out.println("恭喜"+name+"取走了钱:"+money);
                this.money-=money;
                System.out.println("所剩余额:"+this.money);
            }else {
                System.out.println("余额不足");
            }
        }
*/
//    解决方案3
    /*public void drawMoney(double money) {
        String name=Thread.currentThread().getName();
lock.lock();
        try {
            if(this.money>=money){
                System.out.println("恭喜"+name+"取走了钱:"+money);
                this.money-=money;
                System.out.println("所剩余额:"+this.money);
            }else {
                System.out.println("余额不足");
            }
        } finally {    lock.unlock();

        }

        }
*/
    public Account(String cardid, double money) {
        this.cardid = cardid;
        this.money = money;
    }

    public String getCardid() {
        return cardid;
    }

    public void setCardid(String cardid) {
        this.cardid = cardid;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }


}

四、线程池(很重要的知识)

1,创建线程池

方法一:ExecutorServive

使用ExecutorServive的实现类ThreadPoolExecutor自创建一个线程池对象,看代码

ExecutorService pool=new ThreadPoolExecutor(3,5,6,
                TimeUnit.SECONDS,new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

ThreadPoolExecutor里面的一些变量分别是,核心线程,最大线程,临时线程最大存活时间,时间单位,指定任务队列最大数,指定线程工厂默认的就行,这过参数有4种选择看需求。

方法二:Executors

使用Executors(线程池工具类)调用方法创建对象。

这个容易出现bug,不推荐,阿里巴巴java,也是不推荐的。

五、线程池处理Runnable与Callable任务。

1,简单的案例处理

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName()+"hello"+i);
        }
    }
}



import java.util.concurrent.*;

/*int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler*/
public class ThreadPool {
    public static void main(String[] args) {
        ExecutorService pool=new ThreadPoolExecutor(3,5,6,
                TimeUnit.SECONDS,new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
       Runnable t=new MyRunnable();
        pool.execute(t);
        pool.execute(t);
        pool.execute(t);
        pool.execute(t);
        pool.execute(t);

    }
}

Callable与Runnable处理基本一样,不过Callable多了个可以调用get方法取值,与上面创建线程第三种那get用法基本一致。

六、定时器

1、Timer实现

直接创建对象,写就完了,这种问题容易出现,不推荐,推荐第二种。

 Timer timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("www");
            }
        },0,2000);

2、scheduledExecutorService实现

 ScheduledExecutorService s=new ScheduledThreadPoolExecutor(3);
        s.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+ "定时输出:aiiaiiaiai"+new Date()+System.currentTimeMillis());
            }
        },0,2, TimeUnit.SECONDS);

这种创建定时器比较好,就用这。

七、多线程并发并行,与生命周期。

1、并发就是。

线程在间隔极短的时间执行了,看做是同时执行,我算了算大概到纳米级才会出现,时间差异。毫秒级都是看做同时执行的,很夸张了。

2、并行就是。

线程在同一时刻同时执行,不存在时间差的。

3、生命周期

就是线程的生命周期官方提供了6种。

八,总结

加油努力,相信自己。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 线程基础知识:线程是操作系统分配CPU时间片的最小单位,多线程就是指同时运行多个线程,可以提高程序的执行效率和响应速度。 2. 线程同步:多个线程访问共享资源时需要进行同步,常用的同步方式有锁、信号量、事件等,在多线程编程中需要注意同步问题,避免出现死锁、竞争等问题。 3. 线程池:线程池是一种管理和复用线程的机制,可以避免频繁创建和销毁线程的开销,提高程序性能。 4. 异步编程:异步编程是一种高效的多线程编程方式,可以避免阻塞主线程,提高程序的响应速度和吞吐量,常用的异步编程方式有回调、任务、异步/await等。 5. 并发集合类:并发集合类是一种线程安全的数据结构,可以在多线程环境下安全地访问和修改集合中的元素,常用的并发集合类有ConcurrentQueue、ConcurrentDictionary等。 6. 线程调试:多线程编程中常常会出现难以重现或者难以查找的问题,需要使用调试工具进行线程调试,常用的调试工具有Debug、Trace等。 7. 线程性能优化:多线程编程中需要注意性能问题,可以通过调整线程数、使用线程池、优化同步方式等方式提高程序性能。 8. 线程安全性:多线程编程中需要注意线程安全性问题,避免出现数据竞争、死锁、线程泄漏等问题,提高程序的可靠性和稳定性。 9. 并发编程模型:并发编程模型是一种用于描述多线程编程模式的方式,常用的模型有Actor模型、CSP模型、数据流模型等。 10. 并行计算:并行计算是一种高效的计算方式,可以将任务分配到多个线程中执行,常用的并行计算方式有MapReduce、OpenMP、CUDA等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值