zoukankan      html  css  js  c++  java
  • 线程

    如何证明多线程?

    首先我们需要知道可能有哪些线程,哪段代码是属于哪个线程执行,这个区分了才好证明。而且我们证明需要有大量的数据,这样才能体现出效果。

    finalize方法的调用可能是垃圾回收器线程来调用的,如果是则运行该代码有两个线程,那么一定会产生两个线程交替运行的结果(多次尝试),如果没有垃圾回收器线程,那么这个方法的调用就得老老实实地按照顺序接受main方法的安排。
    public class Test1 {
        public static void main(String[] agrs) {
            
            for(int i=0;i<1000000;i++)    
            new my();
            for(int i=0;i<10000;i++)
                System.out.println("A:我是属于main线程的");
            
        }
    
    }
     class my{
    
        @Override
        public void finalize()  {
            // TODO Auto-generated method stub
            System.out.println("B:我是属于垃圾回收器线程的");
        }
         
        
    }

    结果(选取有代表性的一段):

    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    A:我是属于main线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的
    B:我是属于垃圾回收器线程的

    线程的理解

    先定义一个人,就是你自己,你有1000句话跟三个人说(a,b,c),如果你不支持线程,也就是无法跟一个人说话,还没说完就跟另一个人说的技能,那么你说话的顺序将是一条线,先将对a说的话说完,再将对b说的话说完,然后完成对c说的话。如果你支持多线程,那么跟a说几句话之后,这时候b过来插话,你就停止跟a的交流,去跟b说话,跟b说到一半,a又过来插话,于是完成对a的话,再完成对b的话,最后c因为没有插话,还是按照你自己的定义,最后完成c的话。这就有两个线程,一个是自己原本定义好的,第二个那就跟b说话的线程了。

    自己建一个线程,让某些方法不受main线程约束

    自己定义的线程就是上面所说的,将跟b的交流定义成一个线程类,允许b插话,如果将跟c的交流也定义成一个线程类,那么c也能插话了,b和c就打破了本有的规则,可以提前跟你说会话。(争着说话一样,插话的交流都是这样。没有确定性)(不过最后a可能很强大,b和c一点话都插不上)

    public class Test2 {
        public static void main(String[] agrs) {
            for(int i=0;i<10000;i++)
                System.out.println("A:main");
            Mytest m=new Mytest();
            m.start();
            
        }
    
    }
    class Mytest extends Thread{
        public void run() {
            for(int i=0;i<10000;i++) 
                System.out.println("B:我自己的线程,不受main线程约束");
            
        }
    }
    public class Test2 {
        public static void main(String[] agrs) {
            for(int i=0;i<10000;i++)
                System.out.println("A:main");
            Mytest m=new Mytest();
            new Thread(m).start();
            
        }
    
    }
    class Mytest implements Runnable{
        public void run() {
            for(int i=0;i<10000;i++) 
                System.out.println("B:我自己的线程,不受main线程约束");
            
        }
    }

    线程的方法

    String getName()

    获取线程名

    void setName(String name)

    设置线程名

    static Thread currentThread()

    该方法必须写在线程代码里面,写在别的线程程序里面就是显示别的线程了(主要用于实现runnable接口的那种线程里面)

     static void sleep(long millis)

     你会发现输出的结果是一秒输出一个

    public class Test3 {
        public static void main(String[] agrs) throws InterruptedException {
            System.out.println("nihao");
            Thread.sleep(1000);
            System.out.println("nihao");
            Thread.sleep(1000);
            System.out.println("nihao");
            Thread.sleep(1000);
            System.out.println("nihao");
            Thread.sleep(1000);
            System.out.println("nihao");
            Thread.sleep(1000);
            System.out.println("nihao");
            Thread.sleep(1000);
        }
    
    }

    给某个线程加这个方法,可以让有这个方法的线程被最后选择。

    void setDaemon(boolean on)

    设置这个方法的线程的生命受到非守护线程的影响,当非守护线程生命完了之后,守护线程(设置了该方法的线程)就会挂掉。

    void join()

    调用该方法的线程是插入线程,当别的线程在执行时,插入该方法,那么调用该方法的线程就会先执行完。

    void join(long millis)

    设置允许进程插队的时间

    tatic void yield()

    线程让出cpu的方法(还是有不确定性)

    void setPriority(int newPriority) 

    设置线程优先级

    代码的同步

    在使用多线程的同时也有弊端,当一个线程还没完成它的整体工作,就调换到另一个线程(比如你在跟a说话的同时,b过来插话,这时候如果b插上话了,而且当跟a正说“从前。。。。。”,一个完整的话还没说完就会让谈话不愉快)我们要做的就是找到属于一个完整的不可分割的代码块,用synchronized方法传入任何对象锁起来。(传入的对象必须是同一个对象)(同步代码块)

    还可以用同步方法的方式锁起来。

    线程安全问题

    当自己只有一句话跟a,b,c,d说时,你请求跟a说话,a说等一分钟后再说,这时候你还有一句话没说出去,请求跟b说话,b又说等一分钟后再说,于是请求跟c说话,跟c说完之后,a和b又跑过来跟自己说话,程序停止,于是你会发现自己明明说只说一句话的,最后说了三句话。跟期望不符合。于是我们要告诉自己,必须等跟a交流完之后再进行别的,这就没有问题了。将执行的代码块锁起来,关键点是多个线程对象必须用同一把锁才有效。

    死锁问题

    两个线程的代码块都上了锁,而且一个代码块a里面嵌套了另一把锁,但是这个锁的打开需要等待代码块b锁的打开,但是b代码块里面又嵌套了a中使用的锁,就这样我等你,你等我,程序就停在那了。

     线程的通信

    当程序有多个线程时,我们一般都很难控制它们谁先执行,谁后执行,怎么样交替执行。于是通信的作用就在于此。

    public class Test4 {
        public static void main(String[] agrs) {
            final Mytest1 my=new Mytest1();
            new Thread() {
                public void run() {
                    while(true) {
                        try {
                            my.m1();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    while(true) {
                        
                            try {
                                my.m2();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                }
            }.start();
            
            
            
            
            
        }
    
    }
    class Mytest1 {
        
        private int flag=1;
        public void m1() throws InterruptedException {
            
            synchronized(this) {
            if(flag!=1) {
                this.wait();
            }
            System.out.println("B");
            flag=2;
            this.notify();
            }
        }
        public void m2() throws InterruptedException {
            synchronized(this) {
            if(flag!=2) {
                this.wait();
            }
            System.out.println("A");
            flag=1;
            this.notify(); //随机唤醒某个线程
            }
        }
            
            
        
    
    }

    可以看到交替运行

    三个线程的交替运行

    public class Test5 {
        public static void main(String[] agrs) {
            final Mytest5 my=new Mytest5();
            new Thread() {
                public void run() {
                    while(true) {
                        try {
                            my.m1();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    while(true) {
                        
                            try {
                                my.m2();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    while(true) {
                        
                            try {
                                my.m3();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                }
            }.start();
            
            
            
            
            
        }
    
    }
    class Mytest5 {
        
        private int flag=1;
        public void m1() throws InterruptedException {
            
            synchronized(this) {
            while(flag!=1) {
                this.wait();
            }
            System.out.println("A");
            flag=2;
            this.notifyAll();
            }
        }
        public void m2() throws InterruptedException {
            synchronized(this) {
            while(flag!=2) {
                this.wait();
            }
            System.out.println("B");
            flag=3;
            this.notifyAll();
            }
        }
        public void m3() throws InterruptedException {
            synchronized(this) {
            while(flag!=3) {
                this.wait();
            }
            System.out.println("c");
            flag=1;
            this.notifyAll();
            }
        }
            
            
    
    }

    互斥锁和通信

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test6 {
        public static void main(String[] agrs) {
            final Mytest6 my=new Mytest6();
            new Thread() {
                public void run() {
                    while(true) {
                        try {
                            my.m1();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    while(true) {
                        
                            try {
                                my.m2();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    while(true) {
                        
                            try {
                                my.m3();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                }
            }.start();
            
            
            
            
            
        }
    
    }
    class Mytest6 {
        private ReentrantLock r=new ReentrantLock();
        private Condition c1=r.newCondition();
        private Condition c2=r.newCondition();
        private Condition c3=r.newCondition();
        private int flag=1;
        public void m1() throws InterruptedException {
            
            r.lock();
            if(flag!=1) {
                c1.wait();
            }
            System.out.println("A");
            flag=2;
            c2.signal();
            r.unlock();
        }
        public void m2() throws InterruptedException {
            r.lock();
            if(flag!=2) {
                c2.await();
            }
            System.out.println("B");
            flag=3;
            c3.signal();
            r.unlock();
        }
        public void m3() throws InterruptedException {
            r.lock();
            if(flag!=3) {
                c3.wait();
            }
            System.out.println("c");
            flag=1;
            c1.signal();
            r.unlock();
        }
            
            
    
    }

     

  • 相关阅读:
    Spring IOC三种注入方式(接口注入、setter注入、构造器注入)(摘抄)
    java设计模式之代理模式
    JAVA学习中好网站
    程序员学习能力提升三要素
    ognl中的#、%和$
    二级缓存
    hibernate主键自动生成
    专科考研学校要求一览表
    Chapter 3: Connector(连接器)
    Chapter 2: A Simple Servlet Container
  • 原文地址:https://www.cnblogs.com/S-Mustard/p/7629431.html
Copyright © 2011-2022 走看看