zoukankan      html  css  js  c++  java
  • java基础--多线程

    进程:针对操作系统,一个系统多个任务进程。比如开一个视频播放,开一个QQ

    线程:是进程中的运行单元。

    多线程:一个项目或应用可以分多个线程并行执行,由CPU分配时间片进行调用。

    线程的状态

    1.新建状态    new Thread()

    2.就绪状态    start()

    3.运行状态    run

    4.阻塞状态    失去CPU的时间片

    5.线程终止    线程中的方法执行完毕

    创建线程的方式

    1.继承Thread 重写run方法,缺点单继承,不能再继承其他类

    2.实现Runnable接口(静态代理  Thread代理角色)好处:可以继承或实现其他接口

    3.实现Callable接口    优点:可以返回值,可以抛出自定义异常

    合并线程,插队

    join()

    /**
     * 线程阻塞
     * @author Administrator
     *
     */
    public class ZuseThread extends Thread{
    
        public void run() {
            
            for (int i = 0; i < 500; i++) {
                System.out.println("ZuseThread-->"+i);
            }
            
            
        }
        
        public static void main(String[] args) throws InterruptedException {
            
            ZuseThread zuseThread = new ZuseThread();
            zuseThread.start();
            
            for (int i = 0; i < 500; i++) {
                
                if(i==50){
                    //当mian线程执行到i=50的时候mian线程阻塞开始执行ZuseThread线程,执行完后再执行mian线程
    //Thread.yield();静态方法,暂停当前线程mian,让出时间片
    zuseThread.join(); } System.out.println("main-->"+i); } } }

    暂停线程

    yield()   静态方法,暂停下一,不是绝对的,接下是还否暂停取决于CPU

    sleep()    静态方法,不释放锁,一般用于模拟延迟,倒计时

    多线程并发执行,JAVA能保证每个线程都执行,不能保证执行顺序

    线程优先级:1-10   优先级越高获得CPU的时间片的机会越多,不是绝对的

    setPriority(1)

    并发

    多个线程访问一个资源,要确保资源的安全,需要加同步

    1.同步块   synchronized (对象引用){

    }

    2.同步方法  public synchronized void  aaa(){}

    public class TT implements Runnable {
    
        public Integer b = 1000;
    
        public  void m1() throws InterruptedException {
            synchronized(this.b){
                this.b = 20000;
                Thread.sleep(5000);
                System.out.println(b);
            }
        }
    
        public synchronized void m3() throws InterruptedException {
            this.b = 20000;
            Thread.sleep(5000);
            System.out.println(b);
        }
    
    
        public  void m2(){
            System.out.println(b);
    
        }
    
        @Override
        public void run() {
            try {
                m1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    
        public static void main(String []args) throws InterruptedException {
            TT tt = new TT();
            Thread t1 = new Thread(tt);
            t1.start();
            System.out.println("开始");
            Thread.sleep(1000);
            tt.m2();
        }
    }

     线程不安全

    public class Qiangpiao implements Runnable{
        private int num = 50;
        @Override
        public void run() {
            while(true){
                
                if(num<=0){
                    break;
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                System.out.println(Thread.currentThread().getName()+"抢票"+num);
                num--;
            }
            
        }
        
        public static void main(String[] args) {
            Qiangpiao qiangpiao = new Qiangpiao();
            Thread t1 = new Thread(qiangpiao, "甲");
            Thread t2 = new Thread(qiangpiao, "乙");
            Thread t3 = new Thread(qiangpiao, "丙");
            t1.start();
            t2.start();
            t3.start();
            
        }
        
    
    }

    同步关键字

    public class Qiangpiao implements Runnable{
        private int num = 50;
        
        private boolean flag = true;
        
        
        public synchronized void  tongbu(){
            
            if(num<=0){
                flag = false;
                return;
            }
            /*try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            
            System.out.println(Thread.currentThread().getName()+"抢票"+num);
            num--;
            
            
        }
        
        
        
        @Override
        public void run() {
            while(flag){
                tongbu();
                
            }
            
        }
        
        public static void main(String[] args) {
            Qiangpiao qiangpiao = new Qiangpiao();
            Thread t1 = new Thread(qiangpiao, "甲");
            Thread t2 = new Thread(qiangpiao, "乙");
            Thread t3 = new Thread(qiangpiao, "丙");
            t1.start();
            t2.start();
            t3.start();
            
        }
        
    
    }

    死锁

    /**
     * 线程死锁,有同步才会有死锁
     * @author Administrator
     *
     */
    public class Sisuo {
    
        
        public static void main(String[] args) {
            Object money = new Object();
            Object goods = new Object();
            
            Thread1 thread1 = new Thread1(money, goods);
            Thread t1 = new Thread(thread1);
            Thread2 thread2 = new Thread2(money, goods);
            Thread t2 = new Thread(thread2);
            t1.start();
            t2.start();
            
        }
        
    }
    
    
    class Thread1 implements Runnable{
        
        Object money;
        
        Object goods;
        
        
        public Thread1(Object money, Object goods) {
            super();
            this.money = money;
            this.goods = goods;
        }
    
        @Override
        public void run() {
            while(true){
                synchronized (money) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (goods) {
                        
                    }
                }
                System.out.println("一手给钱");
            }
        }
    }
    
    
    class Thread2 implements Runnable{
        
        Object money;
        
        Object goods;
        
        
        public Thread2(Object money, Object goods) {
            super();
            this.money = money;
            this.goods = goods;
        }
    
        @Override
        public void run() {
            while(true){
                synchronized (goods) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (money) {
                        
                    }
                }
                System.out.println("一手给货");
            }
        }
        
        
    }

    解决并发可能出现的死锁:生产者消费者模式

    /**
     * 生产者消费者
     * @author Administrator
     *
     */
    public class TestShengchanzhe {
    
        public static void main(String[] args) {
            
            Movie m = new Movie();
    
            Player player = new Player(m);
            
            Watch watch = new Watch(m);
            
            new Thread(player).start();
            new Thread(watch).start();
            
            
            
        }
    
    }
    
    class Movie{
        
        private String pic;
        //true 生产者生产,消费者等待,生产完成后通知消费
        //false 消费者消费,生产者等待,消费完成后通知生产
        private boolean flag = true;
        
        public synchronized void play(String pic) throws InterruptedException{
            
            if(!flag){
                this.wait();//会释放锁
            }
            
            Thread.sleep(500);
            this.pic = pic;
            this.notify();//通知消费
            this.flag = false;
            System.out.println("生产者生产-->"+pic);
        }
        
        public synchronized void watch() throws InterruptedException{
            if(flag){
                this.wait();
            }
            
            Thread.sleep(200);
            this.notify();
            this.flag = true;
            System.out.println("消费者消费-->"+pic);
            
        }
        
    }
    
    class Player implements Runnable{
        
        Movie m;
        
        public Player(Movie m) {
            super();
            this.m = m;
        }
    
    
        @Override
        public void run() {
            while(true){
                try {
                    m.play("馒头");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
    }
    
    class Watch implements Runnable{
        
        Movie m;
        
        public Watch(Movie m) {
            super();
            this.m = m;
        }
    
        @Override
        public void run() {
            while(true){
                try {
                    m.watch();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
        }
        
    }

     当一个进程有 500 个线程在跑的话,那性能已经是很低很低了。Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当然了,也可以将其改大。
    当某个应用拥有 250 个以上并发的时候,应考虑应用服务器的集群。
    具体能承载多少并发,需要看硬件的配置,CPU 越多性能越高,分配给 JVM 的内存越多性能也就越高,但也会加重 GC 的负担。
    操作系统对于进程中的线程数有一定的限制:
    Windows 每个进程中的线程数不允许超过 2000
    Linux 每个进程中的线程数不允许超过 1000
    另外,在 Java 中每开启一个线程需要耗用 1MB 的 JVM 内存空间用于作为线程栈之用。
    Tomcat的最大并发数是可以配置的,实际运用中,最大并发数与硬件性能和CPU数量都有很大关系的。更好的硬件,更多的处理器都会使Tomcat支持更多的并发。
    Tomcat 默认的 HTTP 实现是采用阻塞式的 Socket 通信,每个请求都需要创建一个线程处理。这种模式下的并发量受到线程数的限制,但对于 Tomcat 来说几乎没有 BUG 存在了。
    Tomcat 还可以配置 NIO 方式的 Socket 通信,在性能上高于阻塞式的,每个请求也不需要创建一个线程进行处理,并发能力比前者高。但没有阻塞式的成熟。
    这个并发能力还与应用的逻辑密切相关,如果逻辑很复杂需要大量的计算,那并发能力势必会下降。如果每个请求都含有很多的数据库操作,那么对于数据库的性能也是非常高的。
    对于单台数据库服务器来说,允许客户端的连接数量是有限制的。
    并发能力问题涉及整个系统架构和业务逻辑。
    系统环境不同,Tomcat版本不同、JDK版本不同、以及修改的设定参数不同。并发量的差异还是满大的。
    maxThreads="1000" 最大并发数
    minSpareThreads="100"///初始化时创建的线程数
    maxSpareThreads="500"///一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。
    acceptCount="700"// 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理

  • 相关阅读:
    Ceph14.2.5 RBD块存储的实战配置和详细介绍,不看后悔! -- <3>
    常见SQL命令总结学习 -- <1>
    全网最详细的新手入门Mysql命令和基础,小白必看!
    全网最详细的Linux命令系列-nl命令
    全网最详细的Linux命令系列-cat命令
    全网最详细的Linux命令系列-touch命令
    全网最详细的Ceph14.2.5集群部署及配置文件详解,快来看看吧! -- <2>
    什么是Ceph存储?什么是分布式存储?简单明了带你学Ceph -- <1>
    一款专注于阅读的博客园主题-(cnblogs-theme-silence)
    Prometheus 配置文件中 metric_relabel_configs 配置--转载
  • 原文地址:https://www.cnblogs.com/jentary/p/6105088.html
Copyright © 2011-2022 走看看