• Java 多线程(一)


    一、线程的理解

     1、同个应用中,多个任务同时进行。就像QQ聊天,打开一个聊天窗口就是一个线程。

     2、线程可以有多个,但cpu每时每刻只做一件事。由于cpu处理速度很快,我们就感觉是同时进行的。所以宏观上,线程时并发进行的;从微观角度看,线程是异步执行的。

     3、使用线程的目的是最大限度的利用cpu资源。想想QQ聊天的时候,如果没有多线程,一个人的信息没有发完另一个人的信息发不过来,会是什么情况~!

    二、java中使用线程

     1、创建线程

    eg1:继承Thread

    class MyThread extends Thread{
        @Override
        public void run() {
         //code
        }
    }

    启动线程方法:new MyThread().start();

    eg2:实现Runnable接口

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            //code
        }
    }

    启动线程方法:new Thread(new MyRunnable()).start();

     2、设置线程优先级

    Thread t = new Thread(myRunnable);
    t.setPriority(Thread.MAX_PRIORITY);//一共10个等级,Thread.MAX_PRIORITY表示最高级10
    t.start();

     3、join,sleep,yield的用法与区别

      join方法:假如你在A线程中调用了B线程的join方法B.join();,这时B线程继续运行,A线程停止(进入阻塞状态)。等B运行完毕A再继续运行。

      sleep方法:线程中调用sleep方法后,本线程停止(进入阻塞状态),运行权交给其他线程。

      yield方法:线程中调用yield方法后本线程并不停止,运行权由本线程和优先级不低于本线程的线程来抢。(不一定优先级高的能先抢到,只是优先级高的抢到的时间长)

     4、结束线程(修改标示符flag为false来终止线程的运行)

    复制代码
    public class ThreadTest {
        public static void main(String[] args) {
            A aa = new A();
            Thread tt = new Thread(aa);
            tt.start();
    
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            aa.shutDown();
        }
    }
    
    class A implements Runnable {
        private boolean flag = true;
    
        public void run() {
            while (flag) {
                System.out.println("AAAA");
            }
        }
    
        public void shutDown() {
            this.flag = false;
        }
    }
    复制代码

     5、线程同步synchronized

      synchronized可以修饰方法,或者方法内部的代码块。被synchronized修饰的代码块表示:一个线程在操作该资源时,不允许其他线程操作该资源。

    复制代码
    public class ThreadTest {
    
        public static void main(String[] args) {
            MyRunnable myRunnable = new MyRunnable();
            new Thread(myRunnable).start();
            new Thread(myRunnable).start();
            new Thread(myRunnable).start();
            new Thread(myRunnable).start();
        }
    
    }
    
    class MyRunnable implements Runnable {
        private int i = 0;
    
        @Override
        public void run() {
            while (true) {
                sumNum();
            }
        }
    
        private synchronized void sumNum() {
            if (i < 100) {
                try {
                    Thread.sleep(1000);
                    i ++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "--------"
                        + i);
            }
        }
    
    }
    复制代码

     6、wait、notify、notifyAll的用法

      wait方法:当前线程转入阻塞状态,让出cpu的控制权,解除锁定。

      notify方法:唤醒因为wait()进入阻塞状态的其中一个线程。

      notifyAll方法: 唤醒因为wait()进入阻塞状态的所有线程。

      这三个方法都必须用synchronized块来包装,而且必须是同一把锁,不然会抛出java.lang.IllegalMonitorStateException异常。

    下面是一个生产者、消费者例子:

    复制代码
    public class ProductConsumer {
        public static int i = 0;
    
        public static void main(String[] args) {
            ProductStack ps = new ProductStack();
            Product product = new Product(ps);
            new Thread(product).start();
    
            Consumer consumer = new Consumer(ps);
            new Thread(consumer).start();
        }
    
    }
    
    class Product implements Runnable {
        ProductStack ps = null; 
        Product(ProductStack ps) {
            this.ps = ps;
        }
        @Override
        public void run() {
            while (true) {
                if (ProductConsumer.i < 100) {
                    ps.push();
                }else{
                    break;
                }
            }
        }
    
    }
    
    class Consumer implements Runnable {
        ProductStack ps = null;
            Consumer(ProductStack ps) {
                this.ps = ps;
            }
    
        @Override
        public void run() {
            while (true) {
                if (ProductConsumer.i < 100) {
                    ps.pop();
                }else{
                    break;
                }
            }
        }
    
    }
    
    class ProductStack {
        boolean isPro = true;
        public synchronized void push() {
            if (!isPro) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            notifyAll();
            ProductConsumer.i++;
            System.out.print("第" + ProductConsumer.i + "个产品,生产者:"
                    + Thread.currentThread().getName());
            isPro = false;
            try {
                Thread.sleep((int) Math.random() * 200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
        }
    
        public synchronized void pop() {
            if (isPro) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            notifyAll();
            System.out.println(",消费者:" + Thread.currentThread().getName());
            isPro = true;
            try {
                Thread.sleep((int) Math.random() * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    【Linux基础】linux下修改ls显示的时间格式
    【Teradata】gtwglobal查看
    【Teradata】tdlocaledef修改默认日期配置
    【Linux基础】文件处理实例
    【Linux基础】awk命令
    【teradata】强制解锁
    第1节:保存文档
    Centos7安装MySQL数据库
    MyBatis框架之异常处理
    spring事务源码分析
  • 原文地址:https://www.cnblogs.com/dhm520/p/8550913.html
Copyright © 2020-2023  润新知