入门示例
Thread 和 Runnable
import java.util.Random;
public class MyThreadWithExtends extends Thread {
String flag;
public MyThreadWithExtends(String flag){
this.flag = flag;
}
@Override
public void run() {
String tname = Thread.currentThread().getName();
System.out.println(tname+"线程的run方法被调用……");
Random random = new Random();
for(int i=0;i<20;i++){
try {
Thread.sleep(random.nextInt(10)*100);
System.out.println(tname+ "...."+ flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread thread1 = new MyThreadWithExtends("a");
Thread thread2 = new MyThreadWithExtends("b");
thread1.start();
thread2.start();
/**
* 如果是调用thread的run方法,则只是一个普通的方法调用,不会开启新的线程
*/
// thread1.run();
// thread2.run();
}
}
import java.util.Random;
public class MyThreadWithExtends extends Thread {
String flag;
public MyThreadWithExtends(String flag){
this.flag = flag;
}
@Override
public void run() {
String tname = Thread.currentThread().getName();
System.out.println(tname+"线程的run方法被调用……");
Random random = new Random();
for(int i=0;i<20;i++){
try {
Thread.sleep(random.nextInt(10)*100);
System.out.println(tname+ "...."+ flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread thread1 = new MyThreadWithExtends("a");
Thread thread2 = new MyThreadWithExtends("b");
thread1.start();
thread2.start();
/**
* 如果是调用thread的run方法,则只是一个普通的方法调用,不会开启新的线程
*/
// thread1.run();
// thread2.run();
}
}
内置锁:synchronized
public class MySynchronized {
public static void main(String[] args) {
final MySynchronized mySynchronized = new MySynchronized();
// final MySynchronized mySynchronized2 = new MySynchronized();
new Thread("thread1") {
public void run() {
synchronized (mySynchronized) {
try {
System.out.println(this.getName()+" start");
int i =1/0; //如果发生异常,jvm会将锁释放
Thread.sleep(5000);
System.out.println(this.getName()+"醒了");
System.out.println(this.getName()+" end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread("thread2") {
public void run() {
synchronized (mySynchronized) { //争抢同一把锁时,线程1没释放之前,线程2只能等待
// synchronized (mySynchronized2) { //如果不是一把锁,可以看到两句话同时打印
System.out.println(this.getName()+" start");
System.out.println(this.getName()+" end");
}
}
}.start();
}
}
volatile
仅当volatile变量能简化代码的实现以及对同步策略的验证时,才会使用它。volatile的正确使用方式包括:确保它们自身状态的可见性,确保它们引用对象的状态的可见性,以及标识一些重要的程序生命周期事件的发生。
典型用法:检查某个状态标记是否退出循环。
线程池
concurrent包中的五大线程池的创建方式:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* 列出并发包中的各种线程池
* @author
*
*/
public class ExecutorDemo {
public static void main(String[] args) {
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
int cpuNums = Runtime.getRuntime().availableProcessors();
System.out.println(cpuNums);
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(cpuNums);
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(8);
ScheduledExecutorService newSingleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
}
}
ExecutorService 的执行方式有两种:submit与execute,
execute只能接受Runnable类型的任务submit不管是Runnable还是Callable类型的任务都可以接受,但是Runnable返回值均为void,所以使用Future的get()获得的还是null
由Callable和Runnable的区别可知:
1、execute没有返回值
2、submit有返回值,所以需要返回值的时候必须使用submit
1、execute中抛出异常
execute中的是Runnable接口的实现,所以只能使用try、catch来捕获CheckedException,通过实现UncaughtExceptionHande接口处理UncheckedException,即和普通线程的处理方式完全一致。
2、submit中抛出异常
不管提交的是Runnable还是Callable类型的任务,如果不对返回值Future调用get()方法,都会吃掉异常
callable 跟runnable的区别
- runnable的run方法不会有任何返回结果,所以主线程无法获得任务线程的返回值
- callable的call方法可以返回结果,但是主线程在获取时是被阻塞,需要等待任务线程返回才能拿到结果
callable:
import java.util.Random;
import java.util.concurrent.Callable;
public class TaskCallable implements Callable<String>{
private int s;
Random r = new Random();
public TaskCallable(int s){
this.s = s;
}
@Override
public String call() throws Exception {
String name = Thread.currentThread().getName();
long currentTimeMillis = System.currentTimeMillis();
System.out.println(name+" 启动时间:" + currentTimeMillis/1000);
int rint = r.nextInt(3);
try {
Thread.sleep(rint*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " is working..."+s);
return s+"";
}
}
runnable:
import java.util.Random;
public class TaskRunnable implements Runnable{
private int s;
public TaskRunnable(int s){
this.s = s;
}
Random r = new Random();
@Override
public void run() {
String name = Thread.currentThread().getName();
long currentTimeMillis = System.currentTimeMillis();
System.out.println(name+" 启动时间:" + currentTimeMillis/1000);
int rint = r.nextInt(3);
try {
Thread.sleep(rint*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " is working..."+s);
}
}
例子对比:
public static void main(String[] args) {
//创建一个线程池
ExecutorService pool = Executors.newCachedThreadPool();
for(int i = 1; i < 5; i++){
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("thread name: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
pool.shutdown();
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService pool = Executors.newFixedThreadPool(4);
for(int i = 0; i < 10; i++){
Future<String> submit = pool.submit(new Callable<String>(){
@Override
public String call() throws Exception {
//System.out.println("a");
Thread.sleep(5000);
return "b--"+Thread.currentThread().getName();
}
});
//从Future中get结果,这个方法是会被阻塞的,一直要等到线程任务返回结果
System.out.println(submit.get());
}
pool.shutdown();
}