t1 输出 ++++++++++++++
t2 输出 ———————–
t3 输出 ******
t1 obj.wait() flag==1
t2 obj.wait() flag ==2
t3 obj.wait() flag ==3
jdk 1.5 5.0
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
与Runnable的区别,1)有返回结果,2)可以抛出检查异常
创建代码:
// 代表一个任务对象
// Callable代表线程中要执行的代码
FutureTask task = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.sleep(2000);
return "ok";
}
});
// 创建和启动新线程
new Thread(task).start();
// 获取返回结果
System.out.println(task.get());
创建有限的线程资源为更多的任务提供服务。享元模式
// java中对线程池的抽象:ExecutorService 创建一个固定大小的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(2);
/*for (int i = 0; i < 10; i++) {
threadPool.submit(()->{
System.out.println(Thread.currentThread().getName()+"任务执行");
});
}*/
// 执行带有返回结果的任务
Future future = threadPool.submit(() -> {
System.out.println(Thread.currentThread().getName()+"执行计算...");
Thread.sleep(1000);
return 10;
});
System.out.println(future.get());
threadPool.shutdown(); // 不接收新任务,当所有任务运行结束,整个线程池关闭
一个核心的ExecutorService的实现类:ThreadPoolExecutor
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue)
corePoolSize 核心线程数目 (最多保留的线程数)
5
maximumPoolSize
10
workQueue 阻塞队列 如果任务超过了核心线程数,进入队列进行排队,直到有空闲的线程
10
如果任务过多,阻塞队列都放不下了,还会创建新的线程来救急
corePoolSize+救急的线程 <= maximumPoolSize(最大线程数)
21 会抛出拒绝提交任务异常
keepAliveTime 生存时间- 针对救急线程
60
unit 时间单位 秒
// 创建固定大小的线程池
Executors.newFixedThreadPool(2);
核心线程数=最大线程数(没有救急线程被创建)
阻塞队列 无界,可以放任意数量的任务,
适合执行数量有限,长时间运行的任务
// 创建缓冲线程池
Executors.newCachedThreadPool()
核心线程数是0, 最大线程数是Integer的最大值(救急线程可以无限创建)
生存时间是60s
适合任务数比较密集,但每个任务执行时间较短的情况
// 创建单线程线程池
Executors.newSingleThreadExecutor()
使用场景:希望多个任务排队执行
区别:
Executors.newSingleThreadExecutor() 线程个数始终为1,不能修改
Executors.newFixedThreadPool(1) 初始时为1,以后还可以修改
// 带有日程安排功能的线程池
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
// 让任务推迟一段时间执行
// 参数1.任务对象, 参数2,3 推迟的时间
/*service.schedule(()->{
System.out.println("执行任务...");
}, 10L, TimeUnit.SECONDS);*/
// 以一定的频率反复执行任务(任务不会重叠)
// 参数1,任务对象, 参数2,初始推迟时间, 参数3,4 时间间隔和单位
/*service.scheduleAtFixedRate(()->{
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello");
}, 0, 1, TimeUnit.SECONDS);*/
// delay表示从上一个任务结束,到下一个任务开始之间的时间
service.scheduleWithFixedDelay(()->{
System.out.println("hello");
}, 0, 1, TimeUnit.SECONDS);
// service.shutdown();
AtomicInteger
AtomicBoolean
…
// 创建原子整数类
private static AtomicInteger i = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int j = 0; j < 5000; j++) {
i.getAndIncrement(); // 获取并且自增 i++
// i.incrementAndGet(); // 自增并且获取 ++i
}
});
Thread t2 = new Thread(() -> {
for (int j = 0; j < 5000; j++) {
i.getAndDecrement(); // 获取并且自减 i--
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
StringBuffer 线程安全
String 不可变类 , 都是线程安全的
Random 线程安全
Vector 实现了List,并且线程安全
Hashtable 实现了Map,并且线程安全
5.0新增的线程安全集合类
ConcurrentHashMap 实现了Map,并且线程安全
ConcurrentSkipListMap 实现了Map(可排序),并且线程安全
CopyOnWriteArrayList 实现了List,并且线程安全
BlockingQueue 阻塞队列
队列 FIFO , first in first out
Queue –> LinkedList
private static BlockingQueue queue = new ArrayBlockingQueue<>(5);
public static void main(String[] args) {
// 生产者线程
new Thread(()->{
for (int i = 0; i < 10; i++) {
Product p = new Product(i);
System.out.println(Thread.currentThread().getName()+"生产了:"+p);
try {
queue.put(p);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// 消费者线程
for (int j = 0; j < 5; j++) {
new Thread(()->{
for (int i = 0; i < 2; i++) {
try {
Product p = queue.take();
System.out.println(Thread.currentThread().getName()+"消费了:"+p);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
// 线程局部变量
private static ThreadLocal local = new ThreadLocal() {
@Override // 初始值
protected Object initialValue() {
return new SimpleDateFormat("yyyy-MM-dd"); // 存入当前线程
}
};
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
SimpleDateFormat sdf = local.get(); // 获取本线程自己的局部变量
Date date = sdf.parse("1951-10-09"); // 每个线程使用的是自己的SimpleDateFormat因此没有争用
System.out.println(Thread.currentThread().getName() + " " + date);
} catch (ParseException e) {
e.printStackTrace();
}
}).start();
}
/*for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("1951-10-09");
System.out.println(Thread.currentThread().getName() + " " + date);
} catch (ParseException e) {
e.printStackTrace();
}
}).start();
}*/
@(西部开源)
public class Example implements Runnable {
public void run() {
while (true) {
}
}
public static void main(String args[]) {
Example ex1 = new Example();
Example ex2 = new Example();
Example ex3 = new Example();
ex1.run();
ex2.run();
ex3.run();
}
}
A. 代码编译失败,不能直接调用run方法
B. 代码编译成功,存在3 个可运行的线程
C. 代码编译成功,存在1 个可运行的线程
public class Example extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String args[]){
Thread t = new Example();
t.start();
t.start();
t.start();
}
}
A. 编译出错
B. 编译正常,运行时有错
C. 编译运行都无错误,产生1 个线程
D. 编译运行都无错误,产生3 个线程
world
改为hello
呢?public class Example extends Thread {
private String data;
public Example(String data) {
this.data = data;
}
public void run() {
synchronized (data) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + " " + data);
}
}
}
public static void main(String args[]) {
Thread t1 = new Example("hello");
Thread t2 = new Example("world");
t1.start();
t2.start();
}
}
A. 先输出10 个hello,然后是10 个world
B. 先输出10 个world,然后是10 个hello
C. 线程不同步,因此交替输出hello 和world
接上题,如果不希望交替输出hello和world,有哪些解决办法?
线程八锁,分别说出下列八种情况的打印结果
情况1:
class Number{
public synchronized void a() {
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
情况2:
class Number{
public synchronized void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
情况3:
class Number{
public synchronized void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
public void c() {
System.out.println(3);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
new Thread(()->{ n1.c(); }).start();
}
情况4:
class Number{
public synchronized void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
情况5:
class Number{
public synchronized static void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
情况6:
class Number{
public synchronized static void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized static void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
情况7:
class Number{
public synchronized static void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
情况8:
class Number{
public synchronized static void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized static void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
创建三个线程,要求如下:
1)第一个线程输出一行100个*
,使用继承Thread 类的写法
2)第二个线程输出一行100个#
,使用实现Runnable 接口的写法
3)第三个线程输出一行100个+
,用lambda表达式(本质仍是Runnable)的写法
接上题
如果希望输出不产生交错,如何解决
接上题
如果希望先输出+
再输出*
最后输出#
,怎么解决
解答:
package org.westos.thread;
import org.junit.Test;
/**
* *************************************
* Copyright (c) 2018 feiyan.com
* All rights reserved.
* *************************************
* *************************************
*
* @Author: think
* @Project: JavaSE
* @Date: Created in 2018/8/12 9:01
* @Since: JDK 1.8
* @Version: 1.0
* @Modified By:
* @Description:
*/
public class HomeworkDemo {
public static final Object OBJ = new Object();
public static void main(String[] args) {
// test3();
// test4();
// test5();
// test6();
//test7();
// test8();
test9();
}
@Test
public void test1() {
class Example implements Runnable {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName());
}
}
}
Example ex1 = new Example();
Example ex2 = new Example();
Example ex3 = new Example();
ex1.run();
ex2.run();
ex3.run();
}
@Test
public void test2() {
class Example extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}
Thread t = new Example();
t.start();
// t.start();
// t.start();
}
public static void test3() {
class Example extends Thread {
private String data;
public Example(String data) {
this.data = data;
}
@Override
public void run() {
synchronized (OBJ) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + data);
}
}
}
}
Thread t1 = new Example("hello");
Thread t2 = new Example("world");
t1.start();
t2.start();
}
public static void test4() {
Number n1 = new Number();
new Thread(() -> {
n1.a();
}).start();
new Thread(() -> {
n1.b();
}).start();
}
public static void test5() {
Number n1 = new Number();
new Thread(() -> {
n1.a();
}).start();
new Thread(() -> {
n1.b();
}).start();
new Thread(() -> {
n1.c();
}).start();
}
public static void test6() {
Number n1 = new Number();
Number n2 = new Number();
new Thread(() -> {
n1.a();
}).start();
new Thread(() -> {
n2.b();
}).start();
}
public static void test7() {
Number n1 = new Number();
new Thread(() -> {
n1.a();
}).start();
new Thread(() -> {
n1.b();
}).start();
}
public static void test8() {
Number n1 = new Number();
Number n2 = new Number();
new Thread(() -> {
n1.a();
}).start();
new Thread(() -> {
n2.b();
}).start();
}
public static void test9() {
final Object obj = new Object();
class T1 extends Thread {
@Override
public void run() {
synchronized (obj) {
for (int i = 0; i < 100; i++) {
System.out.print("*");
}
System.out.println();
}
}
}
new T1().start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj) {
try {
obj.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 100; i++) {
System.out.print("#");
}
System.out.println();
}
}
}).start();
new Thread(() -> {
synchronized (obj) {
try {
obj.wait(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 100; i++) {
System.out.print("+");
}
System.out.println();
}
}).start();
}
}
class Number {
public synchronized static void a() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
public void c() {
System.out.println(3);
}
}