操作系统运行一个程序就会创建一个进程,例如我们一个main函数程序启动了,就会创建一个java进程,然后有一个main主线程和其他线程(至少一个垃圾回收线程),这时我们如果想java做的任务更多时间更少就可以创建更多线程,这样能够最大化利用cpu,更快响应。
代码实例
public class MyThread extends Thread{//继承Thread类
public void run(){
//重写run方法
}
}
public class Main {
public static void main(String[] args){
new MyThread().start();//创建并启动线程
}
}
public class MyThread2 implements Runnable {//实现Runnable接口
public void run(){
//重写run方法
}
}
public class Main {
public static void main(String[] args){
//创建并启动线程
MyThread2 myThread=new MyThread2();
Thread thread=new Thread(myThread);
thread().start();
//或者 new Thread(new MyThread2()).start();
}
}
FutureTask futureTask = new FutureTask(()->7);
new Thread(futureTask).start();
try {
futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Executor框架包括:线程池,Executor,Executors,ExecutorService,
CompletionService,Future,Callable等。
Executor执行Runnable任务
public class TestCachedThreadPool{
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
// ExecutorService executorService = Executors.newFixedThreadPool(5);
// ExecutorService executorService = Executors.newSingleThreadExecutor();
// ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
for (int i = 0; i < 5; i++){
executorService.execute(new TestRunnable());
System.out.println("************* a" + i + " *************");
}
executorService.shutdown();
}
}
class TestRunnable implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName() + "线程被调用了。");
}
}
Executor执行Callable任务
public class CallableDemo{
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
List> resultList = new ArrayList>();
//创建10个任务并执行
for (int i = 0; i < 10; i++){
//使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future future = executorService.submit(new TaskWithResult(i));
//将任务执行结果存储到List中
resultList.add(future);
}
//遍历任务的结果
for (Future fs : resultList){
try{
while(!fs.isDone);//Future返回如果没有完成,则一直循环等待,直到Future返回完成
System.out.println(fs.get()); //打印各个线程(任务)执行的结果
}catch(InterruptedException e){
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}finally{
//启动一次顺序关闭,执行以前提交的任务,但不接受新任务
executorService.shutdown();
}
}
}
}
class TaskWithResult implements Callable{
private int id;
public TaskWithResult(int id){
this.id = id;
}
/**
* 任务的具体过程,一旦任务传给ExecutorService的submit方法,
* 则该方法自动在一个线程上执行
*/
public String call() throws Exception {
System.out.println("call()方法被自动调用!!! " + Thread.currentThread().getName());
//该返回结果将被Future的get方法得到
return "call()方法被自动调用,任务返回的结果是:" + id + " " + Thread.currentThread().getName();
}
}
/** * <三> 使用ExecutorCompletionService管理异步任务 *
* 1. Java中的ExecutorCompletionService本身有管理任务队列的功能
* i. ExecutorCompletionService内部维护列一个队列, 用于管理已完成的任务
* ii. 内部还维护列一个Executor, 可以执行任务
* 2. ExecutorCompletionService内部维护了一个BlockingQueue, 只有完成的任务才被加入到队列中
* 3. 任务一完成就加入到内置管理队列中, 如果队列中的数据为空时, 调用take()就会阻塞 (等待任务完成) * i. 关于完成任务是如何加入到完成队列中的, 请参考ExecutorCompletionService的内部类QueueingFuture的done()方法
* 4. ExecutorCompletionService的take/poll方法是对BlockingQueue对应的方法的封装, 关于BlockingQueue的take/poll方法:
* i. take()方法, 如果队列中有数据, 就返回数据, 否则就一直阻塞;
* ii. poll()方法: 如果有值就返回, 否则返回null * iii. poll(long timeout, TimeUnit unit)方法: 如果有值就返回, 否则等待指定的时间; 如果时间到了如果有值, 就返回值, 否则返回null
* 解决了已完成任务得不到及时处理的问题 */
ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(Executors.newSingleThreadExecutor());
executorCompletionService.submit(()->7);
try {
Future take = executorCompletionService.take();
Integer integer = take.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Java中线程通信协作的最常见的两种方式:
一.syncrhoized加锁的线程的Object类的wait()/notify()/notifyAll()
二.ReentrantLock类加锁的线程的Condition类的await()/signal()/signalAll()
线程间直接的数据交换:
三.通过管道进行线程间通信:1)字节流;2)字符流
ExecutorService executorService = Executors.newCachedThreadPool();
// ExecutorService executorService = Executors.newFixedThreadPool(5);
// ExecutorService executorService = Executors.newSingleThreadExecutor();
// ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
BlockingQueue blockingQueue= new ArrayBlockingQueue(10);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 5, 60, TimeUnit.SECONDS,blockingQueue);
threadPoolExecutor.execute();
package com.jp.oneone;
public class ValueObject {
public static String value = "";
}
package com.jp.oneone;
//生产者
public class P extends Thread{
private String lock;
public P(String lock) {
super();
this.lock = lock;
}
@Override
public void run() {
while (true) {
try {
synchronized (lock) { //当前线程必须获得锁才可以进行下面的操作
if (!ValueObject.value.equals("")) {//如果Value不为空,说明字符串还没被消费,所以调用wait方法,把当前线程(生成线程)阻塞
lock.wait();
}
String value = System.currentTimeMillis() + "_"
+ System.nanoTime();
System.out.println("set的值是" + value);
ValueObject.value = value;//为空的话,则生成
lock.notify();//生成完就唤醒等待该对象锁的线程,(这里只有一个消费者等这个锁,所以就是唤醒的它)
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.jp.oneone;
//消费者
public class C extends Thread {
private String lock;
public C(String lock) {
super();
this.lock = lock;
}
@Override
public void run() {
while (true) {
try {
synchronized (lock) {
if (ValueObject.value.equals("")) {//如果字符串为空,即被消费完了,所以wait等待。
lock.wait();
}
System.out.println("get的值是" + ValueObject.value);
ValueObject.value = "";
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.jp.oneone;
public class Run {
public static void main(String[] args) {
String lock = new String("");
P p = new P(lock);
C r = new C(lock);
p.start();
r.start();
}
}
再来一版
package oneone;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
private ReentrantLock lock = new ReentrantLock();//拿到可重入锁,相当于synchronized的作用
private Condition condition = lock.newCondition();//调用await和signal方法的对象,相当于Object对象(任意对象)的的wait和notify方法
private boolean hasValue = false;
//生产者
public void set() {
try {
lock.lock();//获得锁
while (hasValue == true) {
condition.await(); //没被消费则阻塞该生产线程,当然也释放了锁,进入等锁的队列
}
System.out.println("打印★");
hasValue = true;
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//消费者
public void get() {
try {
lock.lock();
while (hasValue == false) {
condition.await();
}
System.out.println("打印☆");
hasValue = false;
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package oneone;
public class MyThreadA extends Thread {
private MyService myService;
public MyThreadA(MyService myService) {
super();
this.myService = myService;
}
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
myService.set();
}
}
}
package oneone;
public class MyThreadB extends Thread {
private MyService myService;
public MyThreadB(MyService myService) {
super();
this.myService = myService;
}
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
myService.get();
}
}
}
package oneone;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyService myService = new MyService();
MyThreadA a = new MyThreadA(myService);
a.start();
MyThreadB b = new MyThreadB(myService);
b.start();
}
}
class Xc implements Runnable{
public static int chepiao = 100;
//synchronized的作用是,让它所管辖的代码部分,要么全部执行完,要么全部不执行,synchronized既可修饰代码块,又可以修饰函数
// 如果是锁整个方法,可以在方法内加锁,表达上比如public synchronized void run(){,但对于此案例,是两个线程之间竞争售票,因此不适宜锁起来整个方法
//如果synchronized是锁起来整个方法的,synchronized修饰函数不需要传入字符串参数,相当于默认是this
public void run(){
while (true) {
synchronized (" ") {//在需要加锁保证完整运行的代码块旁边加上synchronized (" "){}包裹代码,即可锁起来该部分代码,()内的字符串随意定义
if(chepiao>0){
System.out.println("第" + Thread.currentThread().getName() + "个车站正在卖出第" + (101-chepiao) + "张车票");
--chepiao;
}else{
break;
}
}
}
}
}
public class XianCheng {
public static void main(String [] args){
Thread Xc1 = new Thread(new Xc());//模拟两个车站在卖车票,竞争共同的线程资源
Xc1.start();
Thread Xc2 = new Thread(new Xc());//模拟两个车站在卖车票,竞争共同的线程资源
Xc2.start();
}
}
package com.svse.thread;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 交替打印奇偶数
*功能说明:
*@author:zsq
*create date:2019年5月27日 下午4:34:30
*修改人 修改时间 修改描述
*
*Copyright (c)2019北京智华天成科技有限公司-版权所有
*/
public class AlternatePrinting {
//让两个线程使用同一把锁。交替执行 。
//判断是不是奇数 如果是奇数进入奇数线程执行打印并加一。然后线程释放锁资源。然后让该线程等待
//判断是不是偶数,如果是偶数进入偶数线程执行打印并加一。然后线程释放锁资源。然后让该线程等待
public static AtomicInteger atomicInteger =new AtomicInteger(1);
public static void main(String[] args) {
Thread a=new Thread(new AThread());
Thread b=new Thread(new BThread());
a.start();
b.start();
}
//奇数线程
public static class AThread implements Runnable{
public void run() {
while(true){
synchronized (atomicInteger) {
if(atomicInteger.intValue()%2 !=0){
System.out.println("奇数线程:" + atomicInteger.intValue());
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
atomicInteger.getAndIncrement(); // 以原子方式将当前值加 1。
// 奇数线程释放锁资源
atomicInteger.notify();//执行完操作后释放锁并进入等待
try {
atomicInteger.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
// 奇数线程等待
try {
atomicInteger.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
//偶数线程
public static class BThread implements Runnable{
public void run() {
while(true){
synchronized (atomicInteger) {
if(atomicInteger.intValue()%2 ==0){
System.out.println("偶数线程:"+ atomicInteger.intValue());
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
atomicInteger.getAndIncrement(); // 以原子方式将当前值加 1。
// 偶数线程释放锁资源
atomicInteger.notify();//执行完操作后释放锁并进入等待
try {
atomicInteger.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
try {
// 偶数线程等待
atomicInteger.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
}