您的位置:首页 > 编程语言 > Java开发

Java中的多线程常用方法

2017-05-11 20:11 274 查看
多线程一直是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");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息