java多线程有实现Runnable接口,继承Thread类,或者实现Callable接口。其中Callable接口有还回值。
多线程具有安全问题,在共享数据的时候,数据变量的值会被修改。如果不是共享没有问题,通过加锁,或者采用synchronized 同步方法或者同步代码块,可以实现多线程的安全问题。
实现Runnable接口的需要重写call方法,其是多线程执行的地方。
class RandomNumberTest implements Callable {
private int N=136;
private List<Integer> list=new LinkedList<Integer>();
private ReadWriteLock r=new ReentrantReadWriteLock();
@Override
public Object call() throws Exception {
// r.writeLock().lock();
// synchronized (this){
while (N>0){
Thread.sleep(3);
System.out.println(this+" "+Thread.currentThread()+" "+N);
list.add(N);
N--;
}
// }
// r.writeLock().unlock();
return list;
}
}
Runnable需要Future接口,或者FutureTask辅助,才能实现多线程。
通过Future的get方法取回多线程的返回值。
public static void test() {
RandomNumberTest rnt=new RandomNumberTest();
FutureTask ftk1=new FutureTask(rnt);
FutureTask ftk2=new FutureTask(rnt);
new Thread(ftk1).start();
new Thread(ftk2).start();
try {
LinkedList<Integer> lnk1= (LinkedList) ftk1.get();
for(int elem:lnk1){
System.out.print(elem+" ");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
通过线程池,实现多线程的创建。 JVAV默认提供了4个线程池。BlockingDeque是阻塞队列,存放线程池里面的task。 ThreadPoolExecutor通过execute执行多线程。如果是Callable接口有返回结果的通过submit执行。
public static void tetsExpool() throws ExecutionException, InterruptedException {
RandomNumberTest rnt=new RandomNumberTest();
BlockingDeque<Runnable> bq=new LinkedBlockingDeque<Runnable>(3);
ThreadPoolExecutor t=new ThreadPoolExecutor(3,6,1000L,TimeUnit.SECONDS,bq);
Future ftk1=t.submit(rnt);
Future ftk2=t.submit(rnt);
LinkedList<Integer> lnk1= (LinkedList) ftk1.get();
System.out.println("----------------"+lnk1.size());
for(int elem:lnk1){
System.out.print(elem+" ");
}
}
多线程安全问题很诡异,加锁可能形成死shuo
死锁一般不容易形成,形成了也不好修改,需要打破死锁形成的条件。
死锁类。
class DeadLockDemo implements Runnable {
private int num;
private boolean flag;
public DeadLockDemo(int num,boolean flag){
this.num=num;
this.flag=flag;
}
public void run() {
System.out.println(Thread.currentThread().getName());
while (num > 0) {
if(flag)
{
synchronized (ApplicationListener.b1) {
System.out.println(this + " true " + Thread.currentThread() + " " + num);
num--;
try {
Thread.sleep(3999);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (ApplicationListener.b2) {
System.out.println(this + " " + Thread.currentThread() + " " + num);
num++;
try {
Thread.sleep(60 * 100); // 为测试,占用了就不放
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
else{
synchronized (ApplicationListener.b2) {
num++;
System.out.println(this + " false " + Thread.currentThread() + " " + num);
try {
Thread.sleep(3199);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (ApplicationListener.b1) {
num--;
System.out.println(this + " " + Thread.currentThread() + " " + num);
try {
Thread.sleep(60 * 100); // 为测试,占用了就不放
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}
通过调用会形成死锁。
public static void deadLock(){
DeadLockDemo d1=new DeadLockDemo(33,true);
DeadLockDemo d2=new DeadLockDemo(66,false);
Thread t1=new Thread(d1);
Thread t2=new Thread(d2);
t1.start();
t2.start();
}
情况如下所示。
转载于:https://www.jianshu.com/p/afdd20cc64e7