本文不是深究线程,而是对线程有一个基本的了解。
1、进程与线程
进程是一个执行的程序,是系统进行资源分配的独立单位,而线程是该程序的不同执行序列。
资源 通讯 切换
进程 独占 困难 开销大
线程 共享 容易 开销小
2、线程
2.1创建方式
继承thread,重写run方法
public class Byextend extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args) {
Byextend b = new Byextend();
b.setName("继承声明");
b.start();
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
实现runnalbe接口,重写run方法
public class ByImplement implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args) {
ByImplement byImplement = new ByImplement();
Thread thread = new Thread(byImplement);
thread.setName("实现Runnable声明");
thread.start();
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
实现callable接口,重写call方法(重点是可以有返回值,而且能抛异常)
public class ByCallable implements Callable<String> { //String指定返回的类型
@Override
public String call() throws Exception {
return "impllements by callable";
}
public static void main(String[] args) {
ByCallable callable = new ByCallable();
//futureTask用于接受返回值
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
try {
//futureTask.get()获取返回的值
System.out.println(futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
Executor
以上三种实现方式都是显式的创建一个线程,java给我们提供了一个线程执行器Executor通过使用线程池帮助创建并执行线程
CachedThreadPool
public class ByImplement implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ByImplement());
es.shutdown();
}
}
CachedThreadPool通常会创建与所需数量相同的线程(提高性能),当加入新任务并且不存在可用线程时会创建新的线程提供使用,会回收超过60s未被使用的空闲线程所以节约资源。
FixedThreadPool
public class ByImplement implements Runnable{ .......线程声明run方法同上
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(2);
es.execute(new ByImplement());
es.shutdown();
}
}
FixedThreadPool会根据指定参数创建包含一定数量线程的线程池,以后有且只有该数量的线程,如果有新任务加入会等到有空闲线程可用,当某个线程奔溃时会新增一个线程补充。
SingleThreadPool
public class ByImplement implements Runnable{ .......线程声明run方法同上
public static void main(String[] args) {
ExecutorService es = Executors.newSingleThreadPool();
es.execute(new ByImplement());
es.shutdown();
}
}
SingleThreadPool只有一个线程的线程池,执行任务是有序的,如果该线程出错会有新的线程补充,而FixedThreadPool(1)线程出错不会有新线程补充
使用excute执行实现callable的线程
public class ByCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "impllements by callable";
}
public static void main(String[] args) {
ByCallable callable = new ByCallable();
//futureTask用于接受返回值
FutureTask<String> futureTask = new FutureTask<>(callable);
ExecutorService es = Executors.newSingleThreadExecutor();
es.submit(futureTask); //不再是excute
try {
//futureTask.get()获取返回的值
System.out.println(futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
es.shutdown();
}
}
}
线程常用基础方法
sleep
使当前线程睡眠一定时间(运行到阻塞),让出执行机会,,所有线程都有机会(不考虑优先级),不会让出锁,会有异常产生(interruptedException)
yiled让出执行机会即有运行到就绪(优先级》=当前线程),不会释放锁
join
在当前线程中加入一个线程(合并在一起由并行变为顺序执行)
sleep和yiled是Thread类静态方法
wait
notify/notifyAll
将等待池的对象移到等锁池
以上三个方法只能用于获得锁的代码块中,并且只有同一个对象才能一起使用
线程同步
synchronized(object) 可用于代码框
synchronized 用于方法
锁是属于对象的,
静态方法加锁只影响静态方法(即静态方法的锁属于当前类)
生产者消费者
作者自己写的,若有错误请指出
商品:馒头类
public class Mantou {
private int id;
public Mantou(int id) {
this.id = id;
}
@Override
public String toString() {
return "Mantou{" +
"id=" + id +
'}';
}
}
容器类
public class MtUitl {
private int max = 10;
private int mtnum=1;
private int popn=1;
private List<Mantou>mts = new ArrayList<>();
public void push(){
synchronized (mts){
System.out.println(Thread.currentThread().getName()+"开始生产了");
while(mts.size()==max){
System.out.println("数量足够不用生产");
try {
mts.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mts.notifyAll();
Mantou m = new Mantou(mtnum);
mts.add(m);
mtnum++;
System.out.println(Thread.currentThread().getName()+"生产了"+m);
}
}
public void pop(){
synchronized (mts){
//放置消费超量,一直wait没有响应,多个消费者线程才会出现,单个的时候可以不用
if(popn==21){
return;
}
popn++;
System.out.println(Thread.currentThread().getName()+"开始消费了");
while(mts.size()==0){
System.out.println("没有产品,请稍等。。。。");
try {
mts.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Mantou m = mts.get(mts.size()-1);
System.out.println(Thread.currentThread().getName()+"消费了"+m);
mts.notifyAll();
mts.remove(m);
}
}
}
生产者
public class Producer implements Runnable{
private static int countId=0;
private final int id = ++countId;
private static int mtNum= 1;
private MtUitl mtUitl;
public Producer(MtUitl mtUitl) {
this.mtUitl = mtUitl;
}
@Override
public void run() {
for(;mtNum<20;mtNum++) {
mtUitl.push();
//System.out.println("生产者"+id+"生产了");
}
}
}
消费者
public class Customer implements Runnable {
private static int countId=0;
private final int id = ++countId;
private MtUitl mtUitl;
private static int mt = 1;
public Customer(MtUitl mtUitl) {
this.mtUitl = mtUitl;
}
@Override
public void run() {
for(;mt<20;mt++){
mtUitl.pop();
//System.out.println("消费者"+id+"消费了++++++++++++++++"+mantou);
}
}
}
测试类
public class Test {
public static void main(String[] args) {
MtUitl m = new MtUitl();
Customer customer = new Customer(m);
Customer customer1 = new Customer(m);
Customer customer2 = new Customer(m);
Thread thread1 = new Thread(customer);
thread1.setName("消费者1》》》》》");
Thread thread2 = new Thread(customer1);
thread2.setName("——-----------------------------------------消费者2");
Thread thread3 = new Thread(customer2);
thread3.setName(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>消费者3");
Producer p = new Producer(m);
Producer p1 = new Producer(m);
Thread thread4 = new Thread(p);
thread4.setName("生产者1@@@@@@@@");
Thread thread5 = new Thread(p1);
thread5.setName("@@@@@@@@@@@生产者2");
thread1.start();thread2.start();thread3.start();thread4.start(); thread5.start();
}}