zoukankan      html  css  js  c++  java
  • java学习之多线程(二)

    线程间通讯
      其实就是多个线程在操作同一个资源,但是操作的动作不同。

    案例:对姓名性别的设置与读取。
      代码中标志位可以是boolean flag,也可以是int x,x=(x+1)%2。

      加了同步还出错,于是想同步前提:一是2个以上线程是否同步代码(即代码是对同一个资源的操作);二是同一个锁。

    wait:
    notify():
    notifyAll():
    都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁。
    为什么这些操作线程的方法要定义在Object类中呢?
      因为这些方法在操作同步线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒,不可以对不同锁中的线程进行唤醒。
      也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

    class Res{
        private String name;
        private String sex;
        private boolean flag = false;
        
        public synchronized void set(String name, String sex) {
            while(flag)
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            this.name = name;
            this.sex = sex;
            flag = true;
            this.notifyAll();
        }
        
        public synchronized void out(){
            while(flag)
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            System.out.println(name+"..."+sex);
            flag = false;
            this.notifyAll();
        }
    }
    //对资源进行设置操作
    class Input implements Runnable{
        Res r;
    
        public Input(Res r) {
            this.r = r;
        }
    
        @Override
        public void run() {
            int x = 0;
            if(x==0){
                r.set("mike","man");
            }else{
                r.set("莉莉","女");
            }
            x = (x+1)%2;
        }
    }
    
    //对资源进行读取操作
    class OutPut implements Runnable{
    
        Res r;
    
        public OutPut(Res r) {
            this.r = r;
        }
    
        @Override
        public void run() {
            while (true)
                r.out();
        }
    }
    
    //测试
    public class Test{
        
    
        public static void main(String[] args){
            Res r = new Res();
            Thread t1 = new Thread(new Input(r));
            Thread t2 = new Thread(new OutPut(r));
            t1.start();
            t2.start();
        }
    }

    线程间通讯--生产者消费者:
      jdk1.5 中提供了多线程升级解决方案,将同步synchronized替换成显示Lock操作,将Object中的wait,notify,notifyAll替换了condition对象,该对象可以对Lock锁进行替换。
    该示例中,实现了本方只唤醒对方操作。并且可以执行多个设置和读取操作

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class Res{
        private String name;
        private String sex;
        private boolean flag = false;
        private Lock lock = new ReentrantLock();
        private Condition condition_input = lock.newCondition();
        private Condition condition_output = lock.newCondition();
    
    
        public void set(String name, String sex) {
            lock.lock();
            try {
                while(flag)
                    try {
                        condition_input.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                this.name = name;
                this.sex = sex;
                flag = true;
                condition_output.signal();
            }finally {
                lock.unlock();
            }
    
        }
    
        public void out(){
            lock.lock();
            try {
                while(flag)
                    try {
                        condition_output.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                System.out.println(name+"..."+sex);
                flag = false;
                condition_input.signal();
            }finally {
                lock.unlock();
            }
    
        }
    }
    //对资源进行设置操作
    class Input implements Runnable{
        Res r;
    
        public Input(Res r) {
            this.r = r;
        }
    
        @Override
        public void run() {
            int x = 0;
            if(x==0){
                r.set("mike","man");
            }else{
                r.set("莉莉","女");
            }
            x = (x+1)%2;
        }
    }
    
    //对资源进行读取操作
    class OutPut implements Runnable{
    
        Res r;
    
        public OutPut(Res r) {
            this.r = r;
        }
    
        @Override
        public void run() {
            while (true)
                r.out();
        }
    }
    
    //测试
    public class Test{
    
    
        public static void main(String[] args){
            Res r = new Res();
            Thread t1 = new Thread(new Input(r));
            Thread t2 = new Thread(new OutPut(r));
            t1.start();
            t2.start();
        }
    }

    --------------------------------------------------------------------------------
    多线程:停止线程:
    1.定义循环结束标记
      因为线程运行代码一般都是循环,只要控制了循环即可
    2.使用interrupt(中断)方法
      该方法是结束线程的冻结状态,使线程回到运行状态中来
    注:stop方法已经过时不再使用。

    stop方法已经过时,如何停止线程?
      只有一种,run方法结束。
      开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束。
      显而易见,可以想到用标记来停止线程,但是特殊情况:当线程处于了冻结状态,就不会读取到标记,那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清楚,强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
    Thread类提供该方法interrupt();
    --------------------------------------------------------------------------------
    多线程:守护线程:(类似后台线程):当正在运行的线程都是守护线程时,java虚拟机退出。该方法必须在启动线程前调用。看api
    看见的线程都是前台线程,而后台线程的特点是:当所有的前台线程都结束后后台线程也会结束。

    多线程:Jion方法:等待该线程终止。
    特点:当a线程执行到了b线程的.join()方法时,a就会等待,等b线程都执行完,a才会执行。jion可以用来临时加入线程执行。

    优先级&yield方法
    yield:暂停当前正在执行的线程对象,并执行其他线程。

    在开发中如何使用多线程--使用匿名内部类达到并发效果

    public static void main(String[] args){
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    for (int i=0;i<60;i++)
                        System.out.println(Thread.currentThread().getName()+"..."+i);
                }
            };
            new Thread(r).start();
        }
    }
  • 相关阅读:
    删除Tomcat服务及其它注意
    下拉菜单被js图片挡住
    There are no resources that can be added or removed from the server
    Mysql存中文值乱码
    myeclipse的项目导入到eclipse下,com.sun.org.apache.commons.beanutils.BeanUtils不能导入
    No enclosing instance of type E is accessible. Must qualify the allocation with an enclosing
    winServer2003除默认端口外的其他端口只能本地访问,关闭防火墙即可
    Oracle 11.2.0.3 on windows 2008 r2
    windows2008 r2 卸载GI
    初始化参数(Initialization Parameter)知识合集 based on 11g
  • 原文地址:https://www.cnblogs.com/zhaohuan1996/p/9237647.html
Copyright © 2011-2022 走看看