Java并发编程知识点(1)基本的并发语句

实现多线程的两种方式--Runnable和Thread/线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyRunnable implements Runnable{

	protected int countDown=10;
	private static int taskCount=0;
	private final int id = taskCount++;
	
	public MyRunnable(){}
	public MyRunnable(int countDown){
		this.countDown=countDown;
	}
	public void run(){
		while(countDown-->0){
			System.out.println("#"+id+" ("+(countDown>0?countDown:"liftoff!")+")");
			//告诉其他线程,让同级其他线程执行
			Thread.yield();
		}
	}
	
	public static void main(String[]args){
		
		
		ExecutorService exe = Executors.newCachedThreadPool();
		for(int i=0;i<5;i++){
			//注释处也可以正常运行
//			Thread t = new Thread(new MyRunnable());
//			t.start();
			exe.execute(new MyRunnable());
		}
		//如果不结束,将会一直运行,虽然没有线程了。
		exe.shutdown();
		
	}
}

实现多线程主要有两种方式,一种是实现Runnable接口,一种是直接继承Thread类,两种方式大同小异。实现多线程也可以实现匿名类的方式来实现。上面的例子使用了Runnable接口来实现一个多线程的并发,启动线程有两种那个方式,一种是Tread.start(),一种是使用线程池类似,来调用执行。使用线程池可以更好的管理线程,常见的线程池类型有CacheThreadPool,FixThreadPool,和SingleThreadPool.下面我们来看看FixedThreadPool和SingleThreadPool的执行的例子,我们分别写一个main函数,来执行上面的过程,如下所示:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FixedThreadPool {
	public static void main(String[] args){
		//FixedThreadPool,设置线程池容量为5
		ExecutorService exe = Executors.newFixedThreadPool(5);
		for(int i=0;i<10;i++){
			exe.execute(new MyRunnable());
		}
	}

}

上述没有使用exe.shutdown()方法,我们来看看结果,运行结果如下:


可以看到,每次同时运行的线程只有5个,一开始运行的线程只有0,1,2,3,4,,o退出之后,5开始运行,1退出之后,6开始运行,这就是FixedThreadPool。同时你应该注意到,程序没有结束,但是也不再打印新的东西了。

下面我们来看看SingleThreadPool的用法

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadPool {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService exe = Executors.newSingleThreadExecutor();
		for(int i=0;i<5;i++){
			exe.execute(new MyRunnable());
		}
		exe.shutdown();
		
	}

}
运行结果如下


可以看到无路如何,这些线程都是并行运行的。

有的时候你需要从你的线程返回你需要的值,你如果用Thread来实现,那是比较困难的。但是你可以用下面这种办法啊。

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TaskWithResult implements Callable<Integer>{
	int begin;
	int end;
	
	public TaskWithResult(){
		
	}
	
	public TaskWithResult(int begin,int end){
		this.begin=begin;
		this.end=end;
	}

	@Override
	public Integer call() throws Exception {
		int total=0;
		for(int i=begin;i<end;i++){
			total+=i;
		}
		return total;
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService exe = Executors.newCachedThreadPool();
		ArrayList<Future<Integer>> futureList = new ArrayList<Future<Integer>>();
		for(int i=0;i<100000;i+=10000){
			futureList.add(exe.submit(new TaskWithResult(i,i+10000)));
		}
		exe.shutdown();
		int total=0;
		for(Future f:futureList){
			try {
				Integer i = (Integer) f.get();
				total+=i;
			} catch (InterruptedException | ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(total);
		int total2=0;
		for(int i=0;i<100000;i++){
			total2+=i;
		}
		System.out.println(total2);
	}
}
具体的不多说,主要的思路就是实现了从0加到十万。第一种办法是使用了多线程的做法,分了是个线程,第二种做法是采用了直接加的做法。当然,也不一定谁好谁坏,这个要看虚拟机的支持了。

休眠/让步/优先级/后台线程和ThreadFactory

--sleep,以及TimeUnit类,可以自己参考jdk文档;TimeUnit.[interval].sleep([length】)

--new Thread().yield()方法;
--new Thread(new Runnable()).setPriority(int) 以及new Thread(new Runnable).getPriority();Java一般有10级,分别从1-10;
--重点来说一下后台线程,后台线程也是有Thread的实例对象来调用的,只要你在使用start方法之前调用了setDaemon()方法,那么你就能够将线程变为后台线程。后台线程有一个特性,那就是当前台线程全部结束的时候,不管后台线程有没有结束,它都要全部结束,我们来看个后台线程和ThradFactory结合的例子
import java.util.concurrent.*;

public class MyThreadFactory implements ThreadFactory{

	

	@Override
	public Thread newThread(Runnable r) {
		Thread t = new Thread(r);
		//将所有的线程都设置为后台线程
		t.setDaemon(true);
		return t;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		ExecutorService exe = Executors.newCachedThreadPool(new MyThreadFactory());
		for(int i=0;i<5;i++){
			exe.execute(new Mydaemon());
		}
		exe.shutdown();
		try {
			TimeUnit.SECONDS.sleep(10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}
class Mydaemon implements Runnable{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<5;i++){
			try {
				TimeUnit.SECONDS.sleep(1);
				System.out.println(Thread.currentThread()+" "+this);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}

加入一个线程,join的应用

一个线程可以在其他线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行。如果某个线程在另一个线程t上调用t.join(),此线程将被挂起,直到目标线程结束才恢复。也可以加上一个超时参数,这样如果目标线程在这段时间内到期时还没有结束的话,join方法总是能反回,防止长时间等待。如下所示:


public class Sleeper extends Thread{
	
	public int duration;
	public Sleeper(String name, int sleepTime){
		super(name);
		this.duration = sleepTime;
		start();
	}
	
	public void run(){
		try{
			sleep(duration);
		}catch(InterruptedException e){
//			e.printStackTrace();
			System.out.println(getName()+" is interrupt");
			return;
		}
		System.out.println(getName()+" has awakened");
	}
	
	public static void main(String[] args){
		Sleeper
			sleeper1 = new Sleeper("sleeper1", 1500),
			sleeper2 = new Sleeper("sleeper2", 1500);
		Joiner
			Joiner1 = new Joiner("Joiner1", sleeper1),
			Joiner2 = new Joiner("joiner2", sleeper2);
		sleeper2.interrupt();
	}
}

class Joiner extends Thread{
	private Sleeper sleeper;
	public Joiner(String name,Sleeper sleeper){
		super(name);
		this.sleeper=sleeper;
		start();
	}
	
	public void run(){
		try{
			sleeper.join();
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.println(getName()+" join completed");
	}
	
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值