Java中的多线程常用方法

多线程一直是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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值