多线程和并发

本文详细介绍了Java中的线程概念、进程与线程的关系,包括线程的创建方式(Thread、Runnable和Callable),并发问题、线程状态、线程同步(synchronized和lock)、死锁预防、以及线程池的使用。
摘要由CSDN通过智能技术生成

线程

进程:在操作系统中运行的程序,一个进程可以包含多个线程
程序就是指令和数据的有序集合,静态概念
进程就是执行程序的一次执行过程,动态概念系统资源分配的单元

一个进程中包含多个线程,一个进程至少包含一个线程
线程时cpu调度和执行的单位
线程是独立的执行路径
程序运行时,即使没有自己创建线程。后台也会有多个线程,如主线程,gcxianc
main()是主线程,为系统的入口,用于执行整个程序
在一个进程中如果开辟了多个线程,线程的运行由调度器进行安排调度,调度器与操作系统密切相关,先后顺序不能干预
对同一份资源操作时,会存在资源抢夺的问题,加入并发控制
线程会带来额外的开销
每个线程对自己的工作内存交互,内存控制不当会造成数据不一致

线程创建Thread、Runnable、Callable

继承Thread

1.自定义线程类继承Thread类
重新run()方法,编写线程执行体
创建线程对象,调用start方法();

使用Thread实现网图下载:

package com.ty.threadAndRunableAndCallable;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

public class ThreadDownLoader extends Thread {
    private String url;//网图地址
    private String fileName;//
    public ThreadDownLoader(String url,String fileName){
        this.url = url;
        this.fileName = fileName;
    }

    @Override
    public void run(){
        WebDownLoader webDownLoader = new WebDownLoader();
        webDownLoader.downLoader(url,fileName);
        System.out.println("文件名:"+ fileName);
    }

    public static void main(String[] args) {
        ThreadDownLoader t1 = new ThreadDownLoader("https://pic.rmb.bdstatic.com/bjh/914b8c0f9814b14c5fedeec7ec6615df5813.jpeg", "1.jpeg");
        ThreadDownLoader t2 = new ThreadDownLoader("https://n.sinaimg.cn/sinakd2020723s/213/w2048h1365/20200723/3918-iwtqvyk4060964.jpg", "2.jpg");
        ThreadDownLoader t3 = new ThreadDownLoader("https://file.ccmapp.cn/group1/M00/16/64/rApntl7CSdeAbpYqABArOjGaasg001.jpg", "3.jpg");

        t1.start();
        t2.start();
        t3.start();
    }
}

class WebDownLoader{
    public void downLoader(String url,String fileName){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(fileName));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO exception!!! downLoader Error!!!");
        }
    }
}

实现Runnable

定义MyRunnable类实现Runnable接口
实现run()方法,编写线程体
创建线程对象,调用start()方法启动线程

Thread和Runnable区别

Thread不建议使用,避免OOP单继承局限,
Runnable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐是哦哟牛皋,避免单继承的局限性,灵活方便,方便同一个对象被多个线程使用

多线程模拟出票:并发问题

package com.ty.threadAndRunableAndCallable;

public class ConcurrencyQuestion implements Runnable {

    private int tickerNums = 10;

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

    public static void main(String[] args) {
        ConcurrencyQuestion concurrencyQuestionTicker = new ConcurrencyQuestion();
        new Thread(concurrencyQuestionTicker,"aa").start();
        new Thread(concurrencyQuestionTicker,"bb").start();
        new Thread(concurrencyQuestionTicker,"cc").start();
    }

}

多线程模拟龟兔赛跑

在这里插入图片描述

package com.ty.threadAndRunableAndCallable;

public class ConcurrencyRace implements Runnable{
    private String winner;
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {

            //模拟兔子休息
            if (Thread.currentThread().getName().equals("兔子") && i % 2 == 0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            boolean flag = gameOver(i);
            while (flag){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"--->跑了"+i+"步");
        }
    }

    //判断游戏胜利
    private boolean gameOver(int gepts){
        if (winner != null){
            return true;
        }
        if (gepts == 100){
            System.out.println("=============");
            winner = Thread.currentThread().getName();
            System.out.println("winner is "+ winner);
            return true;
        }
        System.out.println("=====w========");
        return false;
    }

    public static void main(String[] args) {
        ConcurrencyRace race = new ConcurrencyRace();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

实现Callable

在这里插入图片描述

package com.ty.threadAndRunableAndCallable;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CallableWebDownLoader implements Callable<Boolean> {
    private String url; //网图地址
    private String name;//保存地址

    public CallableWebDownLoader(String url,String name){
        this.url = url;
        this.name = name;
    }

    @Override
    public Boolean call() throws Exception {
        WebDownLoaderUseCallable callable = new WebDownLoaderUseCallable();
        callable.downLoader(url,name);
        System.out.println("文件名: "+ name);
        return true;
    }

    public static void main(String[] args) {
        CallableWebDownLoader c1 = new CallableWebDownLoader(
                "https://pic.rmb.bdstatic.com/bjh/914b8c0f9814b14c5fedeec7ec6615df5813.jpeg",
                "D:\\software\\JavaCode\\javaSE\\JavaSE01\\src\\com\\ty\\threadAndRunableAndCallable\\1.jpeg");
        CallableWebDownLoader c2 = new CallableWebDownLoader("" +
                "https://n.sinaimg.cn/sinakd2020723s/213/w2048h1365/20200723/3918-iwtqvyk4060964.jpg",
                "D:\\software\\JavaCode\\javaSE\\JavaSE01\\src\\com\\ty\\threadAndRunableAndCallable\\2.jpg");
        CallableWebDownLoader c3 = new CallableWebDownLoader(
                "https://file.ccmapp.cn/group1/M00/16/64/rApntl7CSdeAbpYqABArOjGaasg001.jpg",
                "D:\\software\\JavaCode\\javaSE\\JavaSE01\\src\\com\\ty\\threadAndRunableAndCallable\\3.jpg");

        ExecutorService es = Executors.newFixedThreadPool(1);
        es.submit(c1);
        es.submit(c2);
        es.submit(c3);
        es.shutdown();
    }
}
class WebDownLoaderUseCallable{
    public void downLoader(String url,String name) {
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO Exception, DownLoad Error!!!");
        }
    }
}

静态代理

真是对象和代理对象都要实现一个接口
代理对象要代理真是对象
好处:代理对象可以做真实对象做不了的事情,真实对象可以专注做自己的事情

package com.ty.threadAndRunableAndCallable;

public class staticProxy {
    public static void main(String[] args) {
        HappyCompany happyCompany = new HappyCompany(new You());
        happyCompany.HappyMarry();
    }

}
interface Marry{
    void HappyMarry();
}
//真实角色
class You implements Marry {
    @Override
    public void HappyMarry() {
        System.out.println("结婚了!我们结婚了!!!");
    }
}
//代理角色
class HappyCompany implements Marry{
    private Marry target;
    public HappyCompany(Marry target){
        this.target = target;
    }
    @Override
    public void HappyMarry() {
        after();
        this.target.HappyMarry();
        before();
    }

    private void after() {
        System.out.println("布置现场。。。。");
    }

    private void before() {
        System.out.println("收拾现场。。。。。");
    }
}

线程状态

在这里插入图片描述
五大状态:创建状态、就绪状态、阻塞状态、死亡状态、运行状态

线程执行流程

在这里插入图片描述

线程方法

在这里插入图片描述

停止线程

并不推荐使用stop(),destroy()
推荐线程自己停下来
建议使用一个标志位进行终止变量,flag=false 则终止线程

线程休眠Sleep

在这里插入图片描述

package com.ty.threadAndRunableAndCallable;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CountDown{


    private static void countDown(){
        int count = 10;
        while (true){
            try {
                Thread.sleep(1000);
                count--;
                if (count<0){
                    break;
                }
                System.out.println(count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        //countDown();
        ControlTime();
    }

    //打印系统时间
    private static void ControlTime(){
        Date date = new Date(System.currentTimeMillis());//打印系统时间
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:dd:ss").format(date));
                date = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

}

线程礼让 yield

在这里插入图片描述

package com.ty.threadAndRunableAndCallable;

public class ThreadYield {
    public static void main(String[] args) {
        Yield yield = new Yield();
        new Thread(yield,"a").start();
        new Thread(yield,"b").start();
    }
}
class Yield implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"线程结束");
    }
}

合并线程Join

待此线程执行结束后,在执行其他线程,其他线程阻塞
可以想象成插队

package com.ty.threadAndRunableAndCallable;

public class ThreadJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("vip 来了"+i);
        }
    }

    public static void main(String[] args) {
        ThreadJoin join = new ThreadJoin();
        Thread thread = new Thread(join);
        thread.start();
        for (int i = 0; i < 20; i++) {
            if (i==10){
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main----"+i);
        }
    }
}

线程状态观测

在这里插入图片描述
一个线程可以在给定时间点处于一个状态,这些状态时不反应任何操作系统线程状态的虚拟机状态

package com.ty.threadAndRunableAndCallable;

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

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

        thread.start();
        state = thread.getState();
        System.out.println(state);//run

        while (state != Thread.State.TERMINATED){//Thread.State.TERMINATED 线程不终止
            try {
                Thread.sleep(100);
                state = thread.getState();
                System.out.println(state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程优先级

在这里插入图片描述

package com.ty.threadAndRunableAndCallable;

public class ThreadPriority {
    public static void main(String[] args) {
        getThreadPriority getThreadPriority = new getThreadPriority();
        Thread t1 = new Thread(getThreadPriority);
        Thread t2 = new Thread(getThreadPriority);
        Thread t3 = new Thread(getThreadPriority);
        Thread t4 = new Thread(getThreadPriority);
        Thread t5 = new Thread(getThreadPriority);
        Thread t6 = new Thread(getThreadPriority);

        t1.setPriority(1);
        t1.start();
        t2.setPriority(3);
        t2.start();
        t3.setPriority(5);
        t3.start();
        t4.setPriority(7);
        t4.start();
        t5.setPriority(Thread.MAX_PRIORITY);
        t5.start();
        t6.start();

    }
}
class getThreadPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-----"+Thread.currentThread().getPriority());
    }
}

守护线程demon

在这里插入图片描述

线程同步

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

同步方法

在这里插入图片描述
在这里插入图片描述

同步块

同步块:synchronized() {}
在这里插入图片描述

同步块解决买票、银行取钱、集合不安全问题

//买票
package com.ty.threadAndRunableAndCallable.notSoft;

public class ThreadNotSoftQuestion {
    public static void main(String[] args) {
        buyTicket buyTicket = new buyTicket();
        new Thread(buyTicket,"aa").start();
        new Thread(buyTicket,"bb").start();
        new Thread(buyTicket,"cc").start();

    }
}

class buyTicket implements Runnable{

    private int num= 10;
    private boolean flag = true;

    @Override
    public void run() {
        while (flag){
            buy();
        }
    }

    private synchronized void buy(){
        if (num <= 0){
            flag = false;
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"---抢到了第 "+(num--)+"张票");
    }
}

package com.ty.threadAndRunableAndCallable.notSoft;

//银行取钱:两个人取钱
public class NotSoftBank {
    public static void main(String[] args) {
        Account account = new Account(100, "基金");
        Drawing you = new Drawing(account,50,"tt");
        Drawing girlFriend = new Drawing(account, 100, "yy");
        you.start();
        girlFriend.start();
    }
}
//银行
class Account{
    int money;// 余额
    String name;//卡号

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

//模拟取钱
class Drawing extends Thread{
    private Account account;//账户
    private int drawingMoney;//取了多少
    private int nowMoney;//现在剩余

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

    }

    @Override
    public void run(){

        synchronized (account){

            if (account.money - drawingMoney < 0){
                System.out.println(Thread.currentThread().getName()+"余额不足,无法取出");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //余额
            account.money = account.money - drawingMoney;
            //手里
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name+"余额为:"+account.money);
            System.out.println(this.getName()+"手里的钱:"+nowMoney);
        }
    }
}


package com.ty.threadAndRunableAndCallable.notSoft;

import java.util.ArrayList;
import java.util.List;

public class NotSoftList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                synchronized (list){
                    list.add(Thread.currentThread().getName());
                }
            }).start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

死锁

在这里插入图片描述

避免死锁的四个方法

在这里插入图片描述

锁 Lock

在这里插入图片描述

synchronized和lock的区别

在这里插入图片描述

线程协作

##线程通信
在这里插入图片描述
均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则就会抛出异常。

线程池

在这里插入图片描述
corePoolSize:核心池的大小
maximumPoolSize:最大线程数
keepAliveTime:线程没有任务时最多保持多长时间会终止
在这里插入图片描述

package com.ty.threadAndRunableAndCallable;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//线程池
public class pool {
    public static void main(String[] args) {
        poolTest poolTest = new poolTest();
        ExecutorService es = Executors.newFixedThreadPool(10);
        es.submit(poolTest);
        es.submit(poolTest);
        es.submit(poolTest);
        es.submit(poolTest);
        es.shutdown();
    }
}
class poolTest implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值