栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java

什么是线程

就是程序运行的单元, 所有的代码都是在线程中执行的

什么是进程

程序运行后, 操作系统会分配独立的内存空间, 这块空间是进程, 有自己编号。 可以通过任务管理器, 结束任务, 其本质就是释放这个进程的空间。

并发与并行

并行:单位时间片内在同时运行
并行:单位时间片内交替执行

线程实现的两种方式

方式一:1.定义一个子类继承(extends)Thread类
2.在子类中重写run方法,并将需要线程开启的代码放入run方法中
3.在测试类中创建Thread子类对象
4.使用子类对象调用start()方法

总结:该方法需要将run方法写进子类代码中,对代码侵入严重,少用。

方式二:1.定义一个实现类,实现Runnable接口
2.重写run()方法,将方法放入run方法中
3.创建Runnable实现类对象
4.创建Thread对象将Runnable实现类对象(也就是任务)放入Thread对象中
5.使用Thread对象调用start方法
注:当然可以使用匿名内部类不过方法太长不建议使用:

     Thread thread = new Thread(new Runnable(){
           public void run(){

            }
     }      
实现

实现Runnable接口:

public class RedBage implements Runnable {
    int count = 3;
    int money = 20;
    int sumMoney = count*money;
    @Override
    public void run() {
        synchronized (this) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (sumMoney > 0) {
                count--;
                sumMoney = count*money;
                System.out.println("恭喜" + Thread.currentThread().getName() + ",您成功抢到一个20元红包,红包还剩"+count);
            } else {
                System.out.println(Thread.currentThread().getName() + "抱歉,红包已经被抢完了,红包个数为:"+count);
            }
        }
    }
}

测试类:

public class RedBageDemo {
    public static void main(String[] args) {
        RedBage redBage = new RedBage();
        ArrayList list = new ArrayList<>();
        Collections.addAll(list,"黄蓉","瑛姑","黄药师","周伯通","郭靖");
        for (int i = 0; i < list.size(); i++) {
        //Thread()中的两个参数,redBage:是必须传入的实现类对象,list.get(i)是给线程起名字不重要
        //线程的名字可以使用Thread.currentThread().getName()获取,Thread.currentThread()获取当前正在运行线程对象。
            Thread thread = new Thread(redBage,list.get(i));
            thread.start();
        }
    }
}
多线程的实现结合线程池 线程池的作用:

解决频繁的创建链接和销毁链接,节约资源和时间。线程池会在池中维护几条线程的存活,当需要调用线程时从线程池中直接使用。

线程池三种创建方式: 方式一:

ExecutorService pool = Executors.newCachedThreadPool();
缺点: 没有上限, 消耗大量的内存

方式二:

ExecutorService pool = Executors.newFixedThreadPool(int count);
缺点: 虽然设定了上限, 但是没有设定闲时的线程的数量

方式三(常用):
ThreadPoolExecutor(int corePoolSize,
            int maximumPoolSize,
            long keepAliveTime,
            TimeUnit unit,
            BlockingQueue workQueue,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handler
            )
//最后两个参数可以不写,使用默认
corePoolSize:核心线程数量
maximumPoolSize:最大线程数量
keepAliveTime:临时线程存活的时间
unit:临时线程存活的时间单位
workQueue:超出任务队列的大小
threadFactory:产生线程的工厂, 目前只有一种方法 Executors.defaultThreadFactory()
handler:超出最大任务后的任务如何处理
		new ThreadPoolExecutor.AbortPolicy()直接拒绝, 并且报异常
		new ThreadPoolExecutor.DiscardPolicy()直接拒绝, 但是不报异常, 最垃圾的!!!!!
		new ThreadPoolExecutor.DiscardOldestPolicy()直接拒绝等待最久的, 更垃圾
	    new ThreadPoolExecutor.CallerRunsPolicy()线程不执行, 交给其他线程, main主线程
方式三演示使用:
ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,30, TimeUnit.SECONDS,new ArrayBlockingQueue<>(5));
多线程创建:

存在两种情况:1.线程之间没有交互;2.线程之间存在信息交互。直接演示第二种,在第二种情况下对第一种进行解释。

情况二演示:

线程间的交互需要用到同步代码块,保证线程的交替执行。作用: 保证一条线程执行代码, 其他线程不能干扰, 能够解决多线程操作共享数据安全问题。当一个线程执行时,另一个线程不能执行,当线程等待时才会释放锁,如何使线程等待:【锁对象.wait()】 。如何唤醒:【锁对象.notifyAll()】;唤醒其他所有线程。例如:

synchronized(锁对象){
	//需要同步的代码
}

注意:需要交互的线程的同步代码块的锁对象需要保持统一。

线程一(Runnable接口实现类):
public class PersonFirst implements Runnable {
    private List list;
    private Gift gift;

    public PersonFirst(List list, Gift gift) {
        this.list = list;
        this.gift = gift;
    }

    //此人false时抢东西
    @Override
    public void run() {
        Random random = new Random();
        while (true) {
        //同步代码块,锁对象是list
            synchronized (list) {
                if (gift.isFlag()) {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
//                    抢东西结束
                    int index = random.nextInt(list.size());
                    String name = list.remove(index);
                    System.out.println(Thread.currentThread().getName() + "抢到商品:" + name);
//                    更改flag状态
                    gift.setFlag(true);
                    //            唤醒其他线程
                    list.notifyAll();
                }
            }
        }
    }
}

线程二:

public class PersonSecond implements Runnable {
//被线程当成锁的对象,可以是任意成员:变量、类对象都可以但要保证唯一性。
    private List list;
    private Gift gift;

    public PersonSecond(List list, Gift gift) {
        this.list = list;
        this.gift = gift;
    }

    //此人true时抢东西
    @Override
    public void run() {
        Random random = new Random();
        while (true) {
        //与线程一的锁对象是同一个对象
            synchronized (list) {
                if (!gift.isFlag()) {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
//                    抢东西结束
                    int index = random.nextInt(list.size());
                    String name = list.remove(index);
                    System.out.println(Thread.currentThread().getName() + "抢到商品:" + name);
//                    更改flag状态
                    gift.setFlag(false);
                    //            唤醒其他线程
                    list.notifyAll();
                }
            }
        }
    }
}

线程间交流状态的对象:

public class Gift {
    private boolean flag;

    public Gift() {
    }

    public Gift(boolean flag) {
        this.flag = flag;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        String[] arr = {"海尔冰箱", "鸟牌电视机", "苏泊尔炒锅", "美的电饭煲", "小新文具", "想你美被罩", "华为mate40手机", "小米拖鞋"};
        ArrayList list = new ArrayList<>();
        List strings = Collections.synchronizedList(list);
        Collections.addAll(list,arr);
        Gift gift = new Gift(true);
//        创建两个线程任务
        ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,30, TimeUnit.SECONDS,new ArrayBlockingQueue<>(5));
        PersonFirst personFirst = new PersonFirst(list, gift);
        PersonSecond personSecond = new PersonSecond(list, gift);
//        将任务发给线程池
        pool.submit(personFirst);
        pool.submit(personSecond);
    }
}

单独多线程的使用:
将同步代码块取消即可,此时线程的执行变为无序状态,那个线程先抢到资源那个线程执行。
可以直接用:

   PersonFirst personFirst = new PersonFirst(list, gift);
   PersonSecond personSecond = new PersonSecond(list, gift);
   Thread thread1 = new Thread(personFirst);
   Thread thread2 = new Thread(personSecond);
   thread1.start();
   thread2.start();
   //放入线程池执行
   ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,30, TimeUnit.SECONDS,new ArrayBlockingQueue<>(5));
   pool.submit(personFirst);
   pool.submit(personSecond);
       
   
方法改进使用单例模式,确保一个类的对象只能被创建一次

单例模式:
1.保证一个类只有一个对象(实例)
2.作用:因为对象只有一个,可以用来共享数据,省去传参给多个类的过程。

实现方式:

饿汉式:
1.私有化构造
2.维护一个private static 修饰的本类对象
3.提供一个static修饰的get方法返回本类对象
实现,例如:

     public class Desk {
         private Desk() {
    }
    private static Desk desk = new Desk();
    
    public static Desk getDesk() {
        return desk;
    }
}

懒汉式:
1.私有化构造
2.维护private static 本类引用
3.提供静态的get方法, 在方法内部判断对象是否为null
4.存在的风险:
可能出现线程安全问题。
5.如何解决:加上同步锁
synchronized(锁对象){
//需要同步的代码
}
代码实现:
Desk单例:

public class Desk {
    private boolean flag = false;

    private static Desk desk = new Desk();

    private Desk() {
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public static Desk getDesk() {
        return desk;
    }

}
     

线程一:

public class Cook implements Runnable {
    @Override
    public void run() {
        while (true) {
        //Desk.getDesk()获取Desk对象,使用了单例模式
            synchronized (Desk.getDesk()) {
                if (Desk.getDesk().isFlag()) {
                    try {
                        Desk.getDesk().wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"蒸包子");
                    Desk.getDesk().setFlag(!Desk.getDesk().isFlag());
                    Desk.getDesk().notifyAll();
                }
            }
        }
    }

}

线程二:

public class Eator implements Runnable{
    @Override
    public void run() {
        while (true){
        //同样是单例操作的是同一个对象
            synchronized (Desk.getDesk()){
                if (!Desk.getDesk().isFlag()){
                    try {
                        Desk.getDesk().wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"吃包子");
                    Desk.getDesk().setFlag(!Desk.getDesk().isFlag());
                    Desk.getDesk().notifyAll();
                }
            }
        }
    }
}

Test类:

public class Test {
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 7, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
        pool.submit(new Cook());
        pool.submit(new Eator());
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/988929.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号