JAVA学习笔记——并发(一)
java中的并发实际上是多线程,要实现并发,需要实现Runnable接口并编写run()方法。下面循序渐进地给出多种运行线程的方法。
1. 直接运行类的方法
新建一个类实现Runnable接口并编写run()方法,然后实例这个类调用其run()方法。
这种方法其实不会启动新的线程,还是只有一个线程,即分配给main()的那个线程。Runnable接口的run方法没有特殊之处,调用这个任务的run方法不会启动新的线程,要启动新的线程,需要显式地将任务分配给线程。
public class test1 implements Runnable {
private int cnt = 5;
@Override
public void run() {
while (cnt-- > 0) {
System.out.println(cnt);
}
}
public static void main(String[] args) {
test1 temp = new test1();
temp.run();
}
}
2. 使用Thread类
我们引入Thread类,将任务test1装进Thread,在t.start()
之后,新的一个线程启动,main()所在的线程和t线程共同运行。
public class test1 implements Runnable {
private int cnt = 5;
@Override
public void run() {
while (cnt-- > 0) {
System.out.println(cnt);
}
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
new Thread(new test1()).start();
}
}
}
3. 使用ExecutorService类
在java5中,并发包java.util.concurrent内新增了Executor,用来管理线程,简化了并发编程。
3.1 使用newCachedThreadPool()方法
使用newCachedThreadPool()方法,在每次execute()
之后,线程开始被创建并运行。 在shutdown()
之前,都可以调用execute()
向管理器提交线程。
public class test1 implements Runnable {
private int cnt = 5;
@Override
public void run() {
while (cnt-- > 0) {
System.out.println(cnt);
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++) {
exec.execute(new test1());
}
exec.shutdown();
}
}
3.2 使用newFixedThreadPool(int)方法
使用newFixedThreadPool(int)方法,线程提前被创建,一次性预先执行高昂代价的线程创建。
public class test1 implements Runnable {
private int cnt = 5;
@Override
public void run() {
while (cnt-- > 0) {
System.out.println(cnt);
}
}
public static void main(String[] args) {
try {
ExecutorService exec = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
exec.execute(new test1());
}
TimeUnit.MILLISECONDS.sleep(500);
exec.shutdown();
}catch (InterruptedException e){
}
}
}
3.3 使用newSingleThreadExecutor()方法
在这种情况下,所有任务按照它们被提交的顺序串行执行,且被分配到同一个线程。
public class test1 implements Runnable {
private int cnt = 5;
@Override
public void run() {
while (cnt-- > 0) {
System.out.println(cnt);
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
exec.execute(new test1());
}
exec.shutdown();
}
}
4. 有返回值的任务
Runnable接口的run()方法没有返回值。如果我们需要在其结束后,能产生返回值的线程,就需要使用Callable接口。应该提交线程给执行器的时候,应该使用submit()
方法,该方法返回Future对象。
public class test2 implements Callable<String> {
private int cnt = 2;
public String call() {
while (cnt-- > 0) {
System.out.println(cnt);
}
return "pxz";
}
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<String> fs = exec.submit(new test2());
exec.shutdown();
try {//Future对象需要捕获以下两个异常
System.out.println(fs.get());
}catch (InterruptedException e){
}
catch (ExecutionException e){
}
}
}