线程
进程:在操作系统中运行的程序,一个进程可以包含多个线程
程序就是指令和数据的有序集合,静态概念
进程就是执行程序的一次执行过程,动态概念系统资源分配的单元
一个进程中包含多个线程,一个进程至少包含一个线程
线程时cpu调度和执行的单位
线程是独立的执行路径
程序运行时,即使没有自己创建线程。后台也会有多个线程,如主线程,gcxianc
main()是主线程,为系统的入口,用于执行整个程序
在一个进程中如果开辟了多个线程,线程的运行由调度器进行安排调度,调度器与操作系统密切相关,先后顺序不能干预
对同一份资源操作时,会存在资源抢夺的问题,加入并发控制
线程会带来额外的开销
每个线程对自己的工作内存交互,内存控制不当会造成数据不一致
线程创建Thread、Runnable、Callable
继承Thread
1.自定义线程类继承Thread类
重新run()方法,编写线程执行体
创建线程对象,调用start方法();
使用Thread实现网图下载:
package com.ty.threadAndRunableAndCallable;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;public class ThreadDownLoader extends Thread {private String url;//网图地址private String fileName;//public ThreadDownLoader(String url,String fileName){this.url = url;this.fileName = fileName;}@Overridepublic void run(){WebDownLoader webDownLoader = new WebDownLoader();webDownLoader.downLoader(url,fileName);System.out.println("文件名:"+ fileName);}public static void main(String[] args) {ThreadDownLoader t1 = new ThreadDownLoader("https://pic.rmb.bdstatic.com/bjh/914b8c0f9814b14c5fedeec7ec6615df5813.jpeg", "1.jpeg");ThreadDownLoader t2 = new ThreadDownLoader("https://n.sinaimg.cn/sinakd2020723s/213/w2048h1365/20200723/3918-iwtqvyk4060964.jpg", "2.jpg");ThreadDownLoader t3 = new ThreadDownLoader("https://file.ccmapp.cn/group1/M00/16/64/rApntl7CSdeAbpYqABArOjGaasg001.jpg", "3.jpg");t1.start();t2.start();t3.start();}
}class WebDownLoader{public void downLoader(String url,String fileName){try {FileUtils.copyURLToFile(new URL(url),new File(fileName));} catch (IOException e) {e.printStackTrace();System.out.println("IO exception!!! downLoader Error!!!");}}
}
实现Runnable
定义MyRunnable类实现Runnable接口
实现run()方法,编写线程体
创建线程对象,调用start()方法启动线程
Thread和Runnable区别
Thread不建议使用,避免OOP单继承局限,
Runnable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐是哦哟牛皋,避免单继承的局限性,灵活方便,方便同一个对象被多个线程使用
多线程模拟出票:并发问题
package com.ty.threadAndRunableAndCallable;public class ConcurrencyQuestion implements Runnable {private int tickerNums = 10;@Overridepublic void run() {while (true){if (tickerNums <= 0){break;}try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"拿到了,第"+(tickerNums--)+"票");}}public static void main(String[] args) {ConcurrencyQuestion concurrencyQuestionTicker = new ConcurrencyQuestion();new Thread(concurrencyQuestionTicker,"aa").start();new Thread(concurrencyQuestionTicker,"bb").start();new Thread(concurrencyQuestionTicker,"cc").start();}}
多线程模拟龟兔赛跑
package com.ty.threadAndRunableAndCallable;public class ConcurrencyRace implements Runnable{private String winner;@Overridepublic void run() {for (int i = 1; i <= 100; i++) {//模拟兔子休息if (Thread.currentThread().getName().equals("兔子") && i % 2 == 0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}boolean flag = gameOver(i);while (flag){break;}System.out.println(Thread.currentThread().getName()+"--->跑了"+i+"步");}}//判断游戏胜利private boolean gameOver(int gepts){if (winner != null){return true;}if (gepts == 100){System.out.println("=============");winner = Thread.currentThread().getName();System.out.println("winner is "+ winner);return true;}System.out.println("=====w========");return false;}public static void main(String[] args) {ConcurrencyRace race = new ConcurrencyRace();new Thread(race,"兔子").start();new Thread(race,"乌龟").start();}
}
实现Callable
package com.ty.threadAndRunableAndCallable;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CallableWebDownLoader implements Callable<Boolean> {private String url; //网图地址private String name;//保存地址public CallableWebDownLoader(String url,String name){this.url = url;this.name = name;}@Overridepublic Boolean call() throws Exception {WebDownLoaderUseCallable callable = new WebDownLoaderUseCallable();callable.downLoader(url,name);System.out.println("文件名: "+ name);return true;}public static void main(String[] args) {CallableWebDownLoader c1 = new CallableWebDownLoader("https://pic.rmb.bdstatic.com/bjh/914b8c0f9814b14c5fedeec7ec6615df5813.jpeg","D:\\software\\JavaCode\\javaSE\\JavaSE01\\src\\com\\ty\\threadAndRunableAndCallable\\1.jpeg");CallableWebDownLoader c2 = new CallableWebDownLoader("" +"https://n.sinaimg.cn/sinakd2020723s/213/w2048h1365/20200723/3918-iwtqvyk4060964.jpg","D:\\software\\JavaCode\\javaSE\\JavaSE01\\src\\com\\ty\\threadAndRunableAndCallable\\2.jpg");CallableWebDownLoader c3 = new CallableWebDownLoader("https://file.ccmapp.cn/group1/M00/16/64/rApntl7CSdeAbpYqABArOjGaasg001.jpg","D:\\software\\JavaCode\\javaSE\\JavaSE01\\src\\com\\ty\\threadAndRunableAndCallable\\3.jpg");ExecutorService es = Executors.newFixedThreadPool(1);es.submit(c1);es.submit(c2);es.submit(c3);es.shutdown();}
}
class WebDownLoaderUseCallable{public void downLoader(String url,String name) {try {FileUtils.copyURLToFile(new URL(url),new File(name));} catch (IOException e) {e.printStackTrace();System.out.println("IO Exception, DownLoad Error!!!");}}
}
静态代理
真是对象和代理对象都要实现一个接口
代理对象要代理真是对象
好处:代理对象可以做真实对象做不了的事情,真实对象可以专注做自己的事情
package com.ty.threadAndRunableAndCallable;public class staticProxy {public static void main(String[] args) {HappyCompany happyCompany = new HappyCompany(new You());happyCompany.HappyMarry();}}
interface Marry{void HappyMarry();
}
//真实角色
class You implements Marry {@Overridepublic void HappyMarry() {System.out.println("结婚了!我们结婚了!!!");}
}
//代理角色
class HappyCompany implements Marry{private Marry target;public HappyCompany(Marry target){this.target = target;}@Overridepublic void HappyMarry() {after();this.target.HappyMarry();before();}private void after() {System.out.println("布置现场。。。。");}private void before() {System.out.println("收拾现场。。。。。");}
}
线程状态
五大状态:创建状态、就绪状态、阻塞状态、死亡状态、运行状态
线程执行流程
线程方法
停止线程
并不推荐使用stop(),destroy()
推荐线程自己停下来
建议使用一个标志位进行终止变量,flag=false 则终止线程
线程休眠Sleep
package com.ty.threadAndRunableAndCallable;import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;public class CountDown{private static void countDown(){int count = 10;while (true){try {Thread.sleep(1000);count--;if (count<0){break;}System.out.println(count);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {//countDown();ControlTime();}//打印系统时间private static void ControlTime(){Date date = new Date(System.currentTimeMillis());//打印系统时间while (true){try {Thread.sleep(1000);System.out.println(new SimpleDateFormat("HH:dd:ss").format(date));date = new Date(System.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}}
线程礼让 yield
package com.ty.threadAndRunableAndCallable;public class ThreadYield {public static void main(String[] args) {Yield yield = new Yield();new Thread(yield,"a").start();new Thread(yield,"b").start();}
}
class Yield implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"线程执行");Thread.yield();System.out.println(Thread.currentThread().getName()+"线程结束");}
}
合并线程Join
待此线程执行结束后,在执行其他线程,其他线程阻塞
可以想象成插队
package com.ty.threadAndRunableAndCallable;public class ThreadJoin implements Runnable{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("vip 来了"+i);}}public static void main(String[] args) {ThreadJoin join = new ThreadJoin();Thread thread = new Thread(join);thread.start();for (int i = 0; i < 20; i++) {if (i==10){try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("main----"+i);}}
}
线程状态观测
一个线程可以在给定时间点处于一个状态,这些状态时不反应任何操作系统线程状态的虚拟机状态
package com.ty.threadAndRunableAndCallable;public class ThreadState {public static void main(String[] args) {Thread thread = new Thread(()->{for (int i = 0; i < 5; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("=============");});//观察线程状态Thread.State state = thread.getState();System.out.println(state); // newthread.start();state = thread.getState();System.out.println(state);//runwhile (state != Thread.State.TERMINATED){//Thread.State.TERMINATED 线程不终止try {Thread.sleep(100);state = thread.getState();System.out.println(state);} catch (InterruptedException e) {e.printStackTrace();}}}
}
线程优先级
package com.ty.threadAndRunableAndCallable;public class ThreadPriority {public static void main(String[] args) {getThreadPriority getThreadPriority = new getThreadPriority();Thread t1 = new Thread(getThreadPriority);Thread t2 = new Thread(getThreadPriority);Thread t3 = new Thread(getThreadPriority);Thread t4 = new Thread(getThreadPriority);Thread t5 = new Thread(getThreadPriority);Thread t6 = new Thread(getThreadPriority);t1.setPriority(1);t1.start();t2.setPriority(3);t2.start();t3.setPriority(5);t3.start();t4.setPriority(7);t4.start();t5.setPriority(Thread.MAX_PRIORITY);t5.start();t6.start();}
}
class getThreadPriority implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"-----"+Thread.currentThread().getPriority());}
}
守护线程demon
线程同步
并发:多个线程同时操作同一资源
由于同一进程的多个线程共享同一块内存空间,方便的同时也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,访问时,加入锁机制synchronized,当一个线程获得对象的排他锁,独占资源时,其他线程必选等待,使用后释放锁即可。
同步方法
同步块
同步块:synchronized() {}
同步块解决买票、银行取钱、集合不安全问题
//买票
package com.ty.threadAndRunableAndCallable.notSoft;public class ThreadNotSoftQuestion {public static void main(String[] args) {buyTicket buyTicket = new buyTicket();new Thread(buyTicket,"aa").start();new Thread(buyTicket,"bb").start();new Thread(buyTicket,"cc").start();}
}class buyTicket implements Runnable{private int num= 10;private boolean flag = true;@Overridepublic void run() {while (flag){buy();}}private synchronized void buy(){if (num <= 0){flag = false;return;}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"---抢到了第 "+(num--)+"张票");}
}
package com.ty.threadAndRunableAndCallable.notSoft;//银行取钱:两个人取钱
public class NotSoftBank {public static void main(String[] args) {Account account = new Account(100, "基金");Drawing you = new Drawing(account,50,"tt");Drawing girlFriend = new Drawing(account, 100, "yy");you.start();girlFriend.start();}
}
//银行
class Account{int money;// 余额String name;//卡号public Account(int money,String name){this.money = money;this.name = name;}
}//模拟取钱
class Drawing extends Thread{private Account account;//账户private int drawingMoney;//取了多少private int nowMoney;//现在剩余public Drawing(Account account,int drawingMoney,String name){super(name);this.account = account;this.drawingMoney = drawingMoney;}@Overridepublic void run(){synchronized (account){if (account.money - drawingMoney < 0){System.out.println(Thread.currentThread().getName()+"余额不足,无法取出");return;}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//余额account.money = account.money - drawingMoney;//手里nowMoney = nowMoney + drawingMoney;System.out.println(account.name+"余额为:"+account.money);System.out.println(this.getName()+"手里的钱:"+nowMoney);}}
}
package com.ty.threadAndRunableAndCallable.notSoft;import java.util.ArrayList;
import java.util.List;public class NotSoftList {public static void main(String[] args) {List<String> list = new ArrayList<>();for (int i = 0; i < 100; i++) {new Thread(()->{synchronized (list){list.add(Thread.currentThread().getName());}}).start();}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(list.size());}
}
死锁
避免死锁的四个方法
锁 Lock
synchronized和lock的区别
线程协作
##线程通信
均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则就会抛出异常。
线程池
corePoolSize:核心池的大小
maximumPoolSize:最大线程数
keepAliveTime:线程没有任务时最多保持多长时间会终止
package com.ty.threadAndRunableAndCallable;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//线程池
public class pool {public static void main(String[] args) {poolTest poolTest = new poolTest();ExecutorService es = Executors.newFixedThreadPool(10);es.submit(poolTest);es.submit(poolTest);es.submit(poolTest);es.submit(poolTest);es.shutdown();}
}
class poolTest implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}