线程

如何证明多线程?

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

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();
    }
        
        

}

 

原文地址:https://www.cnblogs.com/S-Mustard/p/7629431.html