多线程分享

来源:互联网 发布:傲剑北冥神功数据 编辑:程序博客网 时间:2024/04/28 14:54

 今天下午的双周会,轮到了我分享,我给大家分享的是多线程,个人平时也比较喜欢弄这个东西;我这里没有给大家说线程是什么,我的思路是通过讲解关键字,再通过实例来讲解各关键字的使用,以及后面的巩固练习,讲得比较浅,都是一些基本知识。

    这里YY一下,那就是阿里的分享气氛非常好,就是大家都愿意分享,都能够分享,彼此学习,大家共同提高,如了进入正题了。

    一、多线程相关关键字

    Runnable、Thread:线程的父类,区别就是使用Runnable接口不可以使用Thread的相关的特性,如sleep等;
    run:线程类中必须存在的方法;
    start:启动一个线程,经常被面试的人提到,我很郁闷;

    synchronized:同步锁,指定不同的对象,锁的内容不同,如一把锁可以锁门,也可以锁窗户;
    wait:先休息休息,好了的时候再叫我,但别忘了先锁门哦;
    notify:让一个等待的线程活动起来,效率高点;
    notifyAll:让所有等待的线程都起来抢东西了,但我更安全;
    sleep:先休息休息,一会儿自己醒来,除非你不让我休息了;
    interrupt:休息这以久还没有等到,不等了,但是不是中断这个线程;
    setDaemon:守护线程,请不要在乎我的存在,我是为主人服务的;
    join:等等,好了再继续;

    yield:不释放锁的等待,尽可能把优先级交给其它线程,不可以放到synchronized锁定中;
    ThreadLocal:多线程我也不怕共享资源。

    Volatile:参看Java 理论与实践: 正确使用 Volatile 变量

    二、实例

    1、我是一个线程,展示一个简单的线程是怎么样练成的:

    view plaincopy to clipboardprint?
public class IamThread extends Thread {  
    public void run(){  
        System.out.println("I am a thread");  
    }  
}  
或者  
public class IamThread implements Runnable {  
    public void run(){  
        System.out.println("I am a thread");  
    }  
}  
启动线程:  
new Thread(new IamThread()).start() 
public class IamThread extends Thread {
    public void run(){
        System.out.println("I am a thread");
    }
}
或者
public class IamThread implements Runnable {
    public void run(){
        System.out.println("I am a thread");
    }
}
启动线程:
new Thread(new IamThread()).start()

    2、休息休息再说,这个是对sleep的简单使用,休息指定的时间后再工作,这里的时间设的长,是因为3要使用到它:

    view plaincopy to clipboardprint?
public class IamThread extends Thread {  
    public void run() {  
        int i = 0;  
        while (true) {  
            try {  
                sleep(1000000000);  
            } catch (InterruptedException e) {  
            }  
            System.out.println(i++);  
        }  
    }  

public class IamThread extends Thread {
    public void run() {
        int i = 0;
        while (true) {
            try {
                sleep(1000000000);
            } catch (InterruptedException e) {
            }
            System.out.println(i++);
        }
    }
}

    3、睡醒了吧,懒虫,不要一直让他沉睡,过2秒钟醒他一下,“工作”后,再继续睡,然后再过2秒钟再弄醒一下...如些循环,这里需要注意一下方法interrupt(),不要把这个理解为中断线程,理解为把当程线程唤醒更贴切:

    view plaincopy to clipboardprint?
public class RunThread {  
    public static void main(String[] args) {  
        Thread thread = new Thread(new IamThread());  
        thread.start();  
        while (true) {  
            try {  
                Thread.sleep(2000);  
            } catch (InterruptedException e) {  
            }  
            thread.interrupt();  
        }  
    }  

public class RunThread {
    public static void main(String[] args) {
        Thread thread = new Thread(new IamThread());
        thread.start();
        while (true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            thread.interrupt();
        }
    }
}

    4、饭好了叫我,对wait的使用示例,将线程放入到虚拟的wait set中,当对线程使用wait时,但是要想使用wait等待线程,需要注意两点,一是必须要获取锁定,如这里的synchroinzed关键字,二是必须要有notify()或notifyAll()方法来叫醒,否则线程会永远醒不过来:

    view plaincopy to clipboardprint?
public class WaitThread extends Thread {  
    private boolean isReady = false;  
    public synchronized void eat(){  
        if(!isReady){  
            try {  
                wait();  
            } catch (InterruptedException e) {}              
        }  
        System.out.println("I eat happy!");  
    }  
    public synchronized void cook(){  
        isReady = true;  
        //notify();  
        notifyAll();  
    }  

public class WaitThread extends Thread {
    private boolean isReady = false;
    public synchronized void eat(){
        if(!isReady){
            try {
                wait();
            } catch (InterruptedException e) {}           
        }
        System.out.println("I eat happy!");
    }
    public synchronized void cook(){
        isReady = true;
        //notify();
        notifyAll();
    }
}

    5、Join,全部好了再走,JOIN的使用情况是要获取到一个线程或者多个线程执行结果后,再继续执行下面的步骤,如果用采用JOIN,也许启动的线程还没有执行完毕,JVM就退出了;既然JVM可以等到线程执行完后再继续下面的步骤,我们可否使用JOIN来做分布式运算,这个你自己想哦:

    view plaincopy to clipboardprint?
public class JoinThread extends Thread {  
    private static int n = 0;  
    public void run() {  
        for (int i = 0; i < 10; i++)  
            try {  
                addN();  
                //sleep(3); // 为了使运行结果更随机,延迟3毫秒  
            } catch (Exception e) {}  
    }  
    private synchronized void addN() {n++;}  
        public static void main(String[] args) throws Exception {  
        Thread threads[] = new Thread[100];  
        for (int i = 0; i < threads.length; i++) {  
            threads[i] = new JoinThread();  
        }  
        for (int i = 0; i < threads.length; i++) {  
            threads[i].start();  
        }  
        // if (args.length > 0) {  
        for (int i = 0; i < threads.length; i++) {  
            // 100个线程都执行完后继续  
            threads[i].join();  
        }  
        // }  
        System.out.println("n=" + JoinThread.n);  
    }  
}  
public class JoinThread extends Thread {
    private static int n = 0;
    public void run() {
        for (int i = 0; i < 10; i++)
            try {
                addN();
                //sleep(3); // 为了使运行结果更随机,延迟3毫秒
            } catch (Exception e) {}
    }
    private synchronized void addN() {n++;}
        public static void main(String[] args) throws Exception {
        Thread threads[] = new Thread[100];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new JoinThread();
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        // if (args.length > 0) {
        for (int i = 0; i < threads.length; i++) {
            // 100个线程都执行完后继续
            threads[i].join();
        }
        // }
        System.out.println("n=" + JoinThread.n);
    }
}

     注:以上的示例,并不是每次都会得到1000,这个我目前没有想明白是为什么,因为当上面执行到最后的输出的时候,启动的100个线程都已经执行完了,如果你有答案,请告诉我,我会非常感谢。

    6、守护线程,JVM不需要依赖于守护线程是否执行完毕来确定是否退出,他的优先级很低,如垃圾收集集,待其它的线程需要执行时,袒护线程就会等其它线程执行,如果全部执行完了,虚拟机不会在意守护线程是否还有任务在执行,都会退出。简单的理解为守护线程为家仆,其它线程为主人,只需要看主人的脸色,而不会在科家仆的脸色,主人完了,那家仆完不完已经不重要了:

    view plaincopy to clipboardprint?
public class RunDeamonThread {  
    public static void main(String[] args){  
        Thread doorKeeper = new Thread(new DoorKeeper());  
        doorKeeper.setDaemon(true);  
        doorKeeper.start();int i=0;          
        while(i<100){  
            Thread thread = new Thread(new IamThread());  
            thread.start();  
            i++;  
        }  
    }  
}  
class DoorKeeper extends Thread{  
    public void run(){  
        while(true){  
            System.out.println("I am a door guander,don't care me!");  
        }  
    }  

public class RunDeamonThread {
    public static void main(String[] args){
        Thread doorKeeper = new Thread(new DoorKeeper());
        doorKeeper.setDaemon(true);
        doorKeeper.start();int i=0;       
        while(i<100){
            Thread thread = new Thread(new IamThread());
            thread.start();
            i++;
        }
    }
}
class DoorKeeper extends Thread{
    public void run(){
        while(true){
            System.out.println("I am a door guander,don't care me!");
        }
    }
}

    7、ThreadLocal,用于在线程中传递变量

    只有四个方法:
    get() 返回此线程局部变量的当前线程副本中的值。
    initialValue() 返回此线程局部变量的当前线程的“初始值”。只在get或set时执行一次
    remove() 移除此线程局部变量当前线程的值。
    set(T value) 将此线程局部变量的当前线程副本中的值设置为指定值。

    view plaincopy to clipboardprint?
public class ThreadGlobalTest {  
    private static ThreadLocal<String> priviewStatus =   
        new ThreadLocal<String>();  
    public static String getPriviewStatus() {  
        return priviewStatus.get();  
    }  
    public static void setPriviewStatus(String status) {  
        priviewStatus.set(status);  
    }  

public class ThreadGlobalTest {
    private static ThreadLocal<String> priviewStatus =
        new ThreadLocal<String>();
    public static String getPriviewStatus() {
        return priviewStatus.get();
    }
    public static void setPriviewStatus(String status) {
        priviewStatus.set(status);
    }
}

     8、yield,我一直等待,但是我也一直在工作,条件好了我就闪

     view plaincopy to clipboardprint?
public class YieldTest {  
    private volatile boolean ready;  
    //注意此方法不可以加synchronized,因为yield是一种不会释放锁的等待  
    public void doSomething() {  
        while (!ready) {  
            Thread.yield();  
        }  
    }  
    public synchronized void setReady() {  
        ready = true;  
    }  

public class YieldTest {
    private volatile boolean ready;
    //注意此方法不可以加synchronized,因为yield是一种不会释放锁的等待
    public void doSomething() {
        while (!ready) {
            Thread.yield();
        }
    }
    public synchronized void setReady() {
        ready = true;
    }
}

    三、一个巩固实例

    这个实例是别人发到JAVAEYE上面的,我看的蛮有意思的,就贴在这里,

    view plaincopy to clipboardprint?
public class Test {  
    public static void main(String[] args) {  
        MyClass1 myClass = new MyClass1();  
        new MyThread(myClass).start();  
        new MyThread1(myClass).start();  
    }  
}  
class MyClass1 {  
    public synchronized void m1() {  
        System.out.println("m1-1");  
        try {  
            this.wait(); // 暂停改当前线程,并且会释放锁  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        System.out.println("m1-2");  
        try {  
            Thread.sleep(1000); // m1和m2同时暂停1秒钟  
            System.out.println("m1-3");  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("m1-4");  
        m2();  
    }  
    public synchronized void m2() {  
        System.out.println("m2-1");  
        this.notifyAll(); // 叫醒m1  
        System.out.println("m2-2");  
        try {  
            Thread.sleep(1000);  
            System.out.println("m2-3");  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("m2-4");  
        m1();  
    }  
}  
class MyThread extends Thread {  
    private MyClass1 myClass;  
    public MyThread(MyClass1 myClass){  
        this.myClass = myClass;  
    }  
    @Override 
    public void run() {  
        myClass.m1();  
    }  
}  
class MyThread1 extends Thread {  
    private MyClass1 myClass;  
    public MyThread1(MyClass1 myClass){  
        this.myClass = myClass;  
    }  
    @Override 
    public void run() {  
        try { // 暂停10毫秒是为了让m1先执行wait  
            Thread.sleep(10);  
        } catch (InterruptedException e1) {  
            e1.printStackTrace();  
        }  
        myClass.m2();  
    }  

public class Test {
    public static void main(String[] args) {
        MyClass1 myClass = new MyClass1();
        new MyThread(myClass).start();
        new MyThread1(myClass).start();
    }
}
class MyClass1 {
    public synchronized void m1() {
        System.out.println("m1-1");
        try {
            this.wait(); // 暂停改当前线程,并且会释放锁
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("m1-2");
        try {
            Thread.sleep(1000); // m1和m2同时暂停1秒钟
            System.out.println("m1-3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("m1-4");
        m2();
    }
    public synchronized void m2() {
        System.out.println("m2-1");
        this.notifyAll(); // 叫醒m1
        System.out.println("m2-2");
        try {
            Thread.sleep(1000);
            System.out.println("m2-3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("m2-4");
        m1();
    }
}
class MyThread extends Thread {
    private MyClass1 myClass;
    public MyThread(MyClass1 myClass){
        this.myClass = myClass;
    }
    @Override
    public void run() {
        myClass.m1();
    }
}
class MyThread1 extends Thread {
    private MyClass1 myClass;
    public MyThread1(MyClass1 myClass){
        this.myClass = myClass;
    }
    @Override
    public void run() {
        try { // 暂停10毫秒是为了让m1先执行wait
            Thread.sleep(10);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        myClass.m2();
    }
}

    如果没有看明白,就去看这个贴子吧:

    http://www.javaeye.com/topic/964712

    有人褒,有人贬,看你怎么看了,最重要的是,学到东西才是最重要的

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fenglibing/archive/2011/03/25/6278883.aspx

原创粉丝点击