进程:程序的一次执行 线程:进程执行的一段程序片段
main 主线程 一个进程当中会有多个线程
不建议使用 比偏OOP单继承局限性
//创建线程方式1:继承thread类-》重写run()方法,调用start开启线程
public class Thread extends java.lang.Thread {
static int a=1;
@Override
public void run(){
for (int i=a;i<=200;i++){
System.out.println("我在看代码---"+i);
}
}
//main主线程
public static void main(String[] args) {
//创建一个线程对象
Thread thread = new Thread();
//调用 start方法
thread.start();
for (int i=a;i<=200;i++){
System.out.println("我在学习多线程---"+i);
}
}
}
线程开启不一定立即执行 由cpu调度执行
public class Thread2 implements Runnable {
@Override
public void run() {
for (int i=0;i<20;i++){
System.out.println("线程学习"+i);
}
}
public static void main(String[] args) {
Thread2 thread2 = new Thread2();
//创建线程对象,通过线程对象来开启线程,代理
Thread thread = new Thread(thread2);
thread.start();
for (int i=0;i<200;i++){
System.out.println("主函数"+i);
}
}
}
public class Thread5 implements Callable {
private String name;
private String url;
public Thread5(String url,String name) {
this.name=name;
this.url=url;
}
public Thread5() {
}
@Override
public Boolean call() throws Exception {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下载的文件名:"+name);
System.out.println(url);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Thread5 t1 = new Thread5("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1661401277&t=716f8fad1045378c8e5a3ce019db25d6","1.jpg");
Thread5 t2 = new Thread5("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1661401277&t=716f8fad1045378c8e5a3ce019db25d6","2.jpg");
Thread5 t3 = new Thread5("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1661401277&t=716f8fad1045378c8e5a3ce019db25d6","3.jpg");
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1 = ser.submit(t1);
Future<Boolean> r2 = ser.submit(t2);
Future<Boolean> r3 = ser.submit(t3);
//获取结果
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get();
//输出结果
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
//关闭服务
ser.shutdownNow();
}
class WebDownloader{
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异常");
}
}
}
}
//发现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱
public class Thread4Demo implements Runnable {
private int tickNums = 10;
@Override
public void run(){
while(true){
if (tickNums<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"拿到了第"+tickNums--+"票");
}
}
public static void main(String[] args) {
Thread4Demo ticket = new Thread4Demo();
new Thread(ticket,"小明").start();
new Thread(ticket,"老师").start();
new Thread(ticket,"黄牛").start();
}
}
利用多线程模拟归途赛跑
//模拟龟兔赛跑
public class Race implements Runnable{
private static String winner;
@Override
public void run() {
//判断比赛是否结束
for (int i=0;i<=100;i++){
//模拟褥子休息
if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean falg = gameOver(i);
if (falg){
break;
}
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
}
}
private boolean gameOver(int steps){
if (winner!=null){
return true;
}if (steps==100){
winner = Thread.currentThread().getName();
System.out.println("winner is "+winner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"乌龟").start();
new Thread(race,"兔子").start();
}
}
分为静态代理和动态代理 静态代理总结: 真实对象和代理对象都要实现同一个接口 代理对象要代理真实角色 好处 代理对象可以在真实对象执行方法的基础上进行额外操作 真实对象只用专注做自己的事情 静态代理例子:
public class StaticProxy {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new you("xxx"));
new Thread( ()-> System.out.println("i love you ")).start();
weddingCompany.HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
class you implements Marry{
private String name;
public you(String name) {
this.name = name;
}
@Override
public void HappyMarry() {
System.out.println(name+"要结婚");
}
}
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target){
this.target=target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry();//真实对象的调用方法
after();
}
private void after() {
System.out.println("结婚之后");
}
private void before() {
System.out.println("结婚之前");
}
}
函数式编程 Runnable就是一个函数式接口,故可以使用Lambda表达式 使用条件: 必须是函数式接口 函数式接口:函数式接口是只包含一个方法的接口 作用: 避免内部类定义过多 去掉一部分没有意义的代码,留下代码核心
public class LambdaTest {
//3.静态内部类
static class Like2 implements ILike{
@Override
public void lambda() {
System.out.println("i like lambda2");
}
}
public static void main(String[] args) {
ILike iLike = new Like();
iLike.lambda();
iLike = new Like2();
iLike.lambda();
//4.局部内部类
class Like3 implements ILike{
@Override
public void lambda() {
System.out.println("i like lambda3");
}
}
iLike = new Like3();
iLike.lambda();
//5.匿名内部类,没有类的名称,必须借助接口或者父类
iLike=new ILike() {
@Override
public void lambda() {
System.out.println("i like lambda4");
}
};
iLike.lambda();
//6.用lambda简化
iLike = ()-> {
System.out.println("i like lambda5");
};
iLike.lambda();
}
}
//1.定义一个函数接口
interface ILike{
void lambda();
}
//2.实现类
class Like implements ILike{
@Override
public void lambda() {
System.out.println("i like lambda");
}
}
建议线程正常停止-->利用次数,不建议死循环 建议使用标志位-->设置一个标志位(flag=false) 不建议使用stop()或者destroy()等过时或者JDK不建议使用的方法
public class TestStop implements Runnable{
//1.设置一个标识位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag){
System.out.println("run...Thrad"+i++);
}
}
//2.设置一个公开的方法停止线程,转换标识位
public void myStop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 100; i++) {
System.out.println("main"+i);
if (i==90){
testStop.myStop();
System.out.println("线程改停止了");
}
}
}
}
sleep制定当前线程阻塞的毫秒数 sleep存在异常InterruptException; sleep时间达到后线程进入就绪状态 sleep可以模拟网络岩石,倒计时 每个对象都有一个锁,sleep不会释放锁
//模拟倒计时
public class TestSleep2 {
public static void main(String[] args) throws InterruptedException {
// turnDown();
//打印当前系统时间
Date startTime;//获取系统当前时间
while(true){
Thread.sleep(1000);
startTime = new Date(System.currentTimeMillis());
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
}
}
public static void turnDown() throws InterruptedException{
int num=10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if (num<=0){
break;
}
}
}
}
//礼让不一定成功
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a线程").start();
new Thread(myYield,"b线程").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始时间");
Thread.yield();//线程礼让
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
理解为插队
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("vip来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
//我们的线程
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程
for (int i = 0; i < 300; i++) {
if (i==1){
thread.join();
}
System.out.println("main"+i);
}
}
}
先设置优先级,再start 默认为5 thread.setPriority(10) 最小1--最大10
public class TestDeamon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);
thread.start();
new Thread(you).start();
}
}
class God implements Runnable{
@Override
public void run() {
while(true){
System.out.println("god bless you");
}
}
}
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println("Hello world "+ i +" 年");
if (i==100){
System.out.println("Good by world"+i);
}
}
}
}
相当于排队 形成条件:队列+锁(synchronized) 在synchronized代码块中放入想要锁的对象(也就是需要增删改的对象) 以上述第三个为例
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; 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());
}
}
JUC是什么? JUC是java.util.concurrent包的简称,在Java5.0添加,目的就是为了更好的支持高并发任务。让开发者进行多线程编程时减少竞争条件和死锁的问题! 并发与并行的区别: 并发(多线程操作同一个资源,交替执行) CPU一核, 模拟出来多条线程,天下武功,唯快不破,快速交替 并行(多个人一起行走, 同时进行) CPU多核,多个线程同时进行 ; 使用线程池操作
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。(多个线程互相抱着对方需要的资源) 产生死锁的四个必要条件
public class DeadLock {
public static void main(String[] args) {
MakeUp makeUp1 = new MakeUp(0);
MakeUp makeUp2 = new MakeUp(1);
new Thread(makeUp1).start();
new Thread(makeUp2).start();
}
}
class Mirror{
}
class Lipsteak{
}
class MakeUp extends Thread{
static Lipsteak lipsteak = new Lipsteak();
static Mirror mirror = new Mirror();
int choice;
public MakeUp(int choice){
this.choice=choice;
}
@Override
public void run(){
if (choice==0){
synchronized (lipsteak){
System.out.println(choice+"获取lipsteak锁");
synchronized (mirror){
System.out.println(choice+"获取mirror锁");
}
}
}
else{
synchronized (mirror){
System.out.println(choice+"获取mirror锁");
synchronized (lipsteak){
System.out.println(choice+"获取lipsteak锁");
}
}
}
}
}
jdk5.0开始 同步锁使用Lock对象
lock 和 synchronized 区别:
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2 = new TestLock2();
new Thread(testLock2,"1").start();
new Thread(testLock2,"2").start();
}
}
class TestLock2 extends Thread {
int tickNum=10;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while(true) {
try {
lock.lock();
if (tickNum>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tickNum--);
}else{
break;
}
}finally {
lock.unlock();
}
}
}
}
public class TestPC {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
//生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container=container;
}
//生产
@Override
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println("生产了"+i+"个产品");
container.push(new Product(i));
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container=container;
}
//消费者消费
@Override
public void run(){
for (int i = 0; i < 100; i++) {
try {
System.out.println("消费了"+container.pop().id+"个产品");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//产品
class Product{
int id;//产品编号
public Product(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer{
//容器大小
Product[] products = new Product[10];
//容器计数器
int count=0;
//生产者放入产品
public synchronized void push(Product product){
//如果容器满了,需要等待消费者消费
if (count==products.length){
//通知消费者消费,生产者等待
try{
this.wait();
}catch (Exception e){
e.printStackTrace();
}
}
//如果没有满,我们需要丢入产品
products[count]=product;
count++;
//通知消费着消费
this.notifyAll();
}
//消费者消耗产品
public synchronized Product pop() throws InterruptedException {
if (count==0){
//等待生产者生产,消费者等待
this.wait();
}
//如果可以消费
count--;
Product product = products[count];
//使用完了 通知生产者生产
this.notifyAll();
return product;
}
}
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
//生产者 演员
class Player extends Thread{
TV tv;
public Player(TV tv){
this.tv = tv;
}
@Override
public void run(){
for (int i = 0; i < 20; i++) {
if (i%2==0){
this.tv.play("快乐大本营播放中");
}else{
this.tv.play("抖音记录美好生活");
}
}
}
}
//消费者 观众
class Watcher extends Thread{
TV tv;
public Watcher(TV tv){
this.tv = tv;
}
@Override
public void run(){
for (int i = 0; i < 20; i++) {
this.tv.watch();
}
}
}
//产品 节目
class TV{
//演员表演,观众等待 T
//观众观看,演员等待 F
String voice;
boolean flag = true;
//表演
public synchronized void play(String voice) {
if (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了:"+voice);
//通知观众观看
this.notifyAll();//唤醒wait
this.voice=voice;
this.flag=!this.flag;
}
//观看
public synchronized void watch() {
if (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观看了:"+voice);
this.flag=true;
this.notifyAll();
}
}
思路:提前差创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁 实现重复利用。类似交通工具 corePoolSize 线程池大小 maximumPoolSize:最大线程书 keepAliveTime:线程没有任务时最多保持多长时间会停止 JDK5.0起提供了线程池相关的API:Executors和ExecutorService ExecutorService:真正的线程池接口。常见的子类ThreadPoolExecutor Executors:工具类 线程池的工厂类 用于创建并返回不同类型的线程池
public class TestPool {
public static void main(String[] args) {
//1.创建服务,创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//2.关闭连接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}
本文章使用limfx的vscode插件快速发布