Java中的多线程常用方法

来源:互联网 发布:广州周立功单片机 编辑:程序博客网 时间:2024/06/05 17:33

多线程一直是Java的一个重点和难点,前两天小结了一下。

synchronized和Lock

我们都知道ArrayList是非线程安全的,就拿它开刀。下面这个程序简单地展示了synchronized和Lock的用法。

package temp.test;import java.util.ArrayList;import java.util.List;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by 10033 on 2017/5/10. */public class ArrayListThreadTest {    public static Lock lock=new ReentrantLock();    public static List list=new ArrayList();    public static int doRun(int cou) {        while(cou<100000) {            //非同步方法 要么死循环 要么抛异常            /*list.add(10);            ++cou;*/            //两种同步方式            /*synchronized (list) {                list.add(10);                ++cou;            }*/            lock.lock();            list.add(10);            ++cou;            lock.unlock();        }        return cou;    }    public static void main(String[] args) {        Thread1 thread1=new Thread1();        Thread2 thread2=new Thread2();        thread1.start();        thread2.start();        while(thread1.cou+thread2.cou<200000) {            System.out.println(thread1.cou+thread2.cou);        }        System.out.println(list.size() + " @@@@");        System.out.println(thread1.cou+thread2.cou + " ####");    }}class Thread1 extends Thread {    public int cou=0;    @Override    public void run() {        this.cou=ArrayListThreadTest.doRun(cou);    }}class Thread2 extends Thread {    public int cou=0;    @Override    public synchronized void run() {        this.cou=ArrayListThreadTest.doRun(cou);    }}
如果不用同步,那么这个程序要么死循环,要么抛数组下标溢出异常。

tryLock

package temp.test;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by 10033 on 2017/5/10. */public class LockTest {    public static Lock lock=new ReentrantLock();    public static void main(String[] args) {        new Thread(new Runnable() {            public void run() {                boolean flag=false;                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                try {//                    if(lock.tryLock(1, TimeUnit.SECONDS)) { //设置时间来获得锁 超时则放弃                    if(lock.tryLock()) { //第一次没得到就放弃                        flag=true;                    } else {                        System.out.println("没获得锁");                    }                } catch (Exception e) {                    e.printStackTrace();                } finally {                    if(flag) { //确定锁上了才解锁                        lock.unlock();                        System.out.println("解锁啦");                    }                }            }        }).start();        new Thread(new Runnable() {            public void run() {                lock.lock();                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("解锁~~~~");                lock.unlock();            }        }).start();    }}
lock和tryLock的一个不同是lock是阻塞等待锁资源,而tryLock则是试一试(和它名字一样),如果不行,就放弃。

lockInterruptibly

package temp.test;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by 10033 on 2017/5/11. */public class LockInterruptiblyTest {    public static Lock lock=new ReentrantLock();    public static void main(String[] args) throws InterruptedException {        Thread t1=new Thread(new Runnable(){            @Override            public void run() {                try {//                    Thread.sleep(3000);                    lock.lockInterruptibly();                    System.out.println("No Exeception");                    while(true);//                    for(int i=0;i<1000000;i++);                } catch (InterruptedException e) {                    e.printStackTrace();                    System.out.println(Thread.currentThread().getName()+" interrupted.");                } finally {                    lock.unlock();                }            }        });        t1.start();        t1.interrupt();//中断则锁抛异常//        Thread.sleep(1000);    }}
这个和lock一样也是个愣头青,阻塞等待锁,但它所在的线程一旦收到中断信号,它就抛异常。

interrupt

说到中断,那就讲一下interrupt。

package temp.test;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by 10033 on 2017/5/11. */public class InterruptTest {    public static String lock="";    public static Lock locked=new ReentrantLock();    public static Condition condition=locked.newCondition();    public static void main(String[] args) throws InterruptedException {        Thread t1=new Thread(new Runnable() {            @Override            public void run() {                /*synchronized (lock) {                    for(int i=0;i<10;i++)                        System.out.println("@@");                    try {                        lock.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    for(int i=0;i<10;i++)                        System.out.println("##");                }*/                locked.lock();                for(int i=0;i<10;i++)                    System.out.println("@@");                try {                    condition.await();                } catch (InterruptedException e) {                    e.printStackTrace();                }                for(int i=0;i<10;i++)                    System.out.println("##");                locked.unlock();            }        });        t1.start();        Thread.sleep(1000);        t1.interrupt();//唤醒阻塞但抛中断异常        /*synchronized (lock) { //唤醒阻塞不抛异常 wait会主动放弃锁资源            lock.notify();        }*/        /*locked.lock();        condition.signal();        locked.unlock();*/            }}


它就是改变一个状态值,它能唤醒阻塞线程(被sleep和wait的),但会抛中断异常。这里还要说一点,那就是wait和notify方法都得在使用该方法的对象的synchronized同步代码块里使用。如:


signal和await

我们都知道Object有wait,notify,notifyAll三个方法,而在Lock机制里,同样有对应的await,signal,signalAll。

package temp.test;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by 10033 on 2017/5/10. *//** * await和signal必须放在lock之后 */public class SignalAndAwait {    public static Lock lock=new ReentrantLock();    //两个Condition来自同一把锁    public static Condition condition1=lock.newCondition();    public static Condition condition2=lock.newCondition();    public static void main(String[] args) {        new Thread(new Runnable() {            public void run() {                for(int i=0;i<50;i++) {                    lock.lock();                    condition2.signal();                    System.out.println("Thread1");                    try {                        condition1.await();                    } catch (InterruptedException e) {                        e.printStackTrace();                    } finally {                        lock.unlock();                    }                }                lock.lock();                condition2.signal();                lock.unlock();            }        }).start();        new Thread(new Runnable() {            public void run() {                for(int i=0;i<50;i++) {                    lock.lock();                    condition1.signal();                    System.out.println("Thread2");                    try {                        condition2.await();                    } catch (InterruptedException e) {                        e.printStackTrace();                    } finally {                        lock.unlock();                    }                }                lock.lock();                condition1.signal();                lock.unlock();            }        }).start();    }}

这三个方法也必须放在它们对应的lock里执行,即获得锁资源后才能执行,不然会抛异常。


yield和join

yield:将当前线程由运行变为就绪。

join:阻塞当前线程,自己开启的线程先运行完再说。

可以看注释,注释写得比较详细

YieldTest

package threadTest;/** * Created by 10033 on 2017/5/19. */public class YieldTest {    public static void main(String[] args) {        new Thread(new T1()).start();        new Thread(new T2()).start();    }}class T1 implements Runnable {    @Override    public void run() {        System.out.println("T1~~~~~");        Thread.yield();     //从运行到就绪  如果对方线程不争气阻塞了 那我也不客气 接着运行        System.out.println("T1@@@@@");    }}class T2 implements Runnable {    @Override    public void run() {        System.out.println("T266666");        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("T2T2T2");    }}
JoinTest

package threadTest;/** * Created by 10033 on 2017/5/19. */public class JoinTest {    public static void main(String[] args) throws InterruptedException {        /*Thread t2=new Thread(new T4());//        t2.join(); //放在start之前并不会抛异常 但没join效果        t2.start();        t2.join(); //我加入了我就是老大  等我运行完后面的程序才能运行        new Thread(new T3()).start();*/        new Thread(new T3()).start(); //内部有join 说明join只影响当前线程        new Thread(new T4()).start();    }}class T3 implements Runnable {    @Override    public void run() {        System.out.println("T1~~~~~");        System.out.println("T1@@@@@");    }}class T4 implements Runnable {    @Override    public void run() {        System.out.println("T266666");        Thread t=new Thread() {            @Override            public void run() {                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("success");            }        };        t.start();        try {            t.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        /*try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }*/        System.out.println("T2T2T2");    }}


1 0
原创粉丝点击