金华网站建设制作,怎么用vscode做网站,怎么做公司网站制作,学设计的网站有哪些内容文章目录 1.什么是进程2.什么是线程3.线程和进程的区别【面试题】4.并发和并行5.创建线程的两种方式【重点】1.继承Thread2.实现Runnable接口 6.线程下面的几个方法7.线程的同步和锁【重要】 1.什么是进程 是独立的运行程序 比如咱们电脑软件#xff0c;你启动起来以后你启动起来以后他就是一个进程。qq idea 进程需要windows系统的分配。可以获取当前的系统的网卡内存显卡等 1.独立性 各个进程之间是相互的独立的互不影响 的。录屏软件和idea没有关系的 2.互斥性 每个软件系统都会分配一个独立端口号如果启动一个软件以后他的端口号97。 如果再启动另外一个软件另外一个软件如果端口也是97这个程序就启动不了端口被占用的 脑海里面知道开启的软件就是一个进程 即可
2.什么是线程 进程是由多个或者一个线程组成的。每个进程至少得有一个线程的支撑。 脑海里面这样来想一个进程qq,qq里面很多个线程在执行。线程的执行 支撑起来了进程的执行。 把一个人比作一个进程那么你身体里面的细胞就是线程。如果没有细胞。这个人还存在吗不存在的 进程包含了线程线程是组成进程的最小基本单位 特性: 1.抢占式运行的【重要】 CPU在执行的时候按照时间片来执行的单位的时间片是抢占是执行 比如 idea qq 抢占CPU的比如qq的线程抢到cpuidea线程等待 我是一个cpu。你们问我问题。75个线程。同时来问我问题吗不是 抢着问。一个问。然后其他人等待。这个人甚至还没有问完其他的某一个人 抢到我了他问我。大概就是效果 2.资源共享性 一个线程可以共享当前CPU 网卡等 Java程序: 一个Java程序就是一个进程 Demo1 就是一个应用程序 就是一个进程 一个Java程序Demo1里面至少 几个线程 两个 main主函数线程 JVM垃圾回收器线程 3.线程和进程的区别【面试题】
进程是一个应用程序是独立的
线程是进程中最小的基本单位。
把进程比作生产车间每个流水线就是一个线程
进程有独立性和互斥性
线程有抢占式资源共享特性
4.并发和并行 并发:同时发生轮流交替执行 并行:真正意义的同时执行 比如 你去饭店点了两个菜生活中拿个筷子轮流夹菜哦这就是并发场景 端起盘子同时倒到嘴里面这就是并行场景 5.创建线程的两种方式【重点】
1.继承Thread 创建线程的两种方式 一个是将一个类声明为Thread的子类。 这个子类应该重写run方法 。 然后可以分配并启动子类的实例。 package com.qfedu.a_thread;// 一个是将一个类声明为Thread的子类。
// 这个子类应该重写run类的方法Thread 。
// 然后可以分配并启动子类的实例。
class MyThread1 extends Thread{Overridepublic void run() {for (int i 0; i 500; i) {System.out.println(我是myThread1线程: i);}}
}
class MyThread2 extends Thread {Overridepublic void run() {//run方法中写功能代码 就是一个线程中执行的一个功能for (int i 0; i 500; i) {System.out.println(我是mythread2线程: i);}}
}
public class Demo1 {public static void main(String[] args) {//官方手册中说要去实例化Thread的子类并启动线程MyThread1 myThread1 new MyThread1();//启动线程 使用start方法 在主线程中开启子线程myThread1.start();MyThread2 myThread2 new MyThread2();myThread2.start();//现在有几个线程? 3个//一个是MyThread1线程 一个是主线程main 一个垃圾回收机制线程for (int i 0; i 500; i) {System.out.println(主函数线程: i);}//发现先执行了主线程然后再执行子线程然后又执行主线程//这就线程的抢占式的运行//三个线程//你自己吃三盘菜咋吃//一盘菜代表一个线程一盘菜夹一下随机的吧。//开启一个线程就是在执行一个任务。//上面这个代码你们执行结果和我执行的结果一样吗绝对不一样的//抢占式的随机执行线程的}
}
练习:main主线程 打印100遍的吃大盘鸡子线程1 打印100遍的吃水煮肉片子线程2 打印100遍的吃毛血旺一定要注意打印的结果多执行几遍看看每次执行的结果是否一样2.实现Runnable接口 另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例在创建Thread时作为参数传递并启动。 package com.qfedu.a_thread;//另一种方法来创建一个线程是声明实现类Runnable接口。
// 那个类然后实现了run方法。
// 然后可以分配类的实例(创建类的对象)在创建Thread实例时作为参数传递并启动。
class MyThread3 implements Runnable {Overridepublic void run() {for (int i 0; i 100; i) {System.out.println(MyThread3: i);}}
}
class MyaThread4 implements Runnable {Overridepublic void run() {for (int i 0; i 100; i) {System.out.println(MyThread4: i);}}
}
public class Demo2 {public static void main(String[] args) {MyThread3 myThread3 new MyThread3();//Thread(Runnable target) 参数是Runnable这个接口对象//分配一个新的 Thread对象。Thread thread new Thread(myThread3);thread.start();MyaThread4 myaThread4 new MyaThread4();Thread thread1 new Thread(myaThread4);thread1.start();for (int i 0; i 100; i) {System.out.println(main主线程: i);}//有几个线程做任务的线程 3个 一个是main主线程 一个是MyThread3//一个MyThread4这个线程//可以发现运行的结果是随机执行的}
}
6.线程下面的几个方法 构造方法 Thread()分配一个新的 Thread对象。 无参构造方法Thread(Runnable target)分配一个新的 Thread对象。 有参构造Thread(Runnable target, String name)分配一个新的 Thread对象。并起名字 线程方法 static ThreadcurrentThread()返回对当前正在执行的线程对象的引用StringgetName()返回此线程的名称。voidsetName(String name)将此线程的名称更改为等于参数 name 。intgetPriority()返回此线程的优先级。voidsetPriority(int newPriority)更改此线程的优先级。设置优先并不一定优先只是增加了执行的概率。最小值是1最大值是10默认的是5static voidsleep(long millis)使当前正在执行的线程以指定的毫秒数暂停暂时停止执行具体取决于系统定时器和调度程序的精度和准确性。 package com.qfedu.b_threadfun;class MyThread1 implements Runnable {Overridepublic void run() {Thread thread Thread.currentThread();//此时这个thread对象是MyThread1这个线程//对子线程设置名字thread.setName(mythread1子线程);System.out.println(thread.getName());//Thread-0}
}
class MyThread2 implements Runnable {Overridepublic void run() {Thread thread Thread.currentThread();System.out.println(thread.getName());//狗蛋}
}
public class Demo1 {public static void main(String[] args) {//currentThread() 获取当前线程对象Thread thread Thread.currentThread();//现在thread 这个对象是哪个线程主线程//为啥是main主线程//给main主线程设置名字thread.setName(主线程);//获取的是main主线程的名字Jvm会给主线程还有其他线程一个默认的名字System.out.println(thread.getName());//main
// MyThread1 myThread1 new MyThread1();
// Thread thread1 new Thread( myThread1);
// thread1.start();new Thread(new MyThread1()).start();//Java中默认的主线程叫main 子线程叫Thread-0 Thread-1....//默认的有名字咱们能不能对线程自定义名字能//我在启动MyThread2的这个线程的时候顺便起名字MyThread2 myThread2 new MyThread2();//myThread2线程的名字就叫狗蛋是在创建线程的时候就已经起好名字了Thread thread1 new Thread(myThread2, 狗蛋);thread1.start();}
}
package com.qfedu.b_threadfun;class MyThread3 implements Runnable {Overridepublic void run() {//想看一下MyThread3这个线程的优先级是几Thread thread Thread.currentThread();thread.setPriority(10);System.out.println(thread.getPriority());for (int i 0; i 100; i) {System.out.println(MyThread3线程: i);}}
}
class MyThread4 implements Runnable {Overridepublic void run() {//想看一下MyThread3这个线程的优先级是几Thread thread Thread.currentThread();thread.setPriority(1);System.out.println(thread.getPriority());for (int i 0; i 100; i) {System.out.println(MyThread4线程: i);}}
}
public class Demo2 {public static void main(String[] args) {//默认的优先级都是5能不能手动去修改某一个线程的优先级//可以Thread thread Thread.currentThread();//主线程的优先级设置1//thread.setPriority(1);//获取主线程的优先级System.out.println(thread.getPriority());//5//优先级 1 ~10 1的优先级最低 10的优先级最高//jvm默认线程的优先级是5
// for (int i 0; i 100; i) {
// System.out.println(主线程: i);
// }new Thread(new MyThread3()).start();new Thread(new MyThread4()).start();//所以优先级不要用啦并不一定真正的优先//线程执行的结果不可控很尴尬}
}
package com.qfedu.b_threadfun;class MyThread5 implements Runnable {Overridepublic void run() {try {//发现 Thread.sleep 有一个运行时异常//但是发现没有抛出只有try-catch 为啥?//sleep方法写在了run方法中了因为//run方法是重写的 父类的 public abstract void run();//父类有抛出吗没有抛出重写是比较严格的//父类没有抛出子类也同样不能抛出Thread.sleep(10000);//10秒} catch (InterruptedException e) {e.printStackTrace();}for (int i 0; i 500; i) {System.out.println(MyThread5 i);}}
}
class MyThread6 implements Runnable {Overridepublic void run() {for (int i 0; i 500; i) {System.out.println(MyThread6 i);}}
}
public class Demo3 {public static void main(String[] args) {new Thread(new MyThread5()).start();new Thread(new MyThread6()).start();//发现运行的结果是不可控的是随机的抢占式的//咱们接下来学习一个东西叫sleep 让某一个线程睡一会儿//这个线程在睡觉的期间不会去抢占cpu 不执行//现在我让MyTread5睡了一会儿。就意味着绝对MyThread6线程先执行//实现可控的效果//思考sleep方法再开发的时候敢用不敢用//不敢用。睡多久你知道吗睡多久合适不能确定//cpu最大利用化。不可能让cpu闲置//如果sleep睡眠时间少的话还是抢占//如果sleep睡眠你时间太长的话就会cpu就会闲置//没有办法把控的 接下来要学习锁}
}
回顾
1.新建线程的两种方式1.继承Thread2.实现Runnable接口【开发要用的】代码要自己学会写的
2.线程的方法Thread.currentThread();获取当前线程对象setPriority();设置优先级的getPriority(); 获取当前线程的优先级getName()得到线程的名字setName();设置线程的名字sleep();线程的休眠
7.线程的同步和锁【重要】 为什么要进行线程的同步 Java是允许多线程多个线程当多个线程操作同一个资源咋操作的时候会导致得到或者打印的数据不准确。从而发生冲突。咋解决加同步锁。 美团
淘票票
这个两个线程都去麦同一场次的票
结果美团卖出去一张1排1列的票
结果淘票票也卖出去了1排1列的票 你感觉合适吗
就是上面的这种结果不合适的分享同一个资源的时候要保证分享资源的数据合法性分析结果:
package com.qfedu.c_sync;//最理想的状态
//先线程1进入到ticket50,循环 循环结束以后 此时
//tiket49了
//循环第二次的时候 线程2抢到资源了 此时ticket49
//循环 打印49 tiket-- ticket48了
//循环第三次的时候 线程2 抢到资源了 此时ticket48
//打印卖第48张票。ticket-- tiket47
//线程1又抢到循环
//现在的情况是有可能两个线程同时进入到while循环
//
class MySync implements Runnable {int ticket 50;Overridepublic void run() {//while (true) {//死循环//两个线程都进入到了循环了//此时两个线程所持有的ticket 都是50//但是两个线程都要往下执行//有可能线程1 先执行了sout(50) 线程2在等待哦//线程1执行了--操作并出了循环 线程1ticket 49//线程1又抢到循环了 sout(49) tiket--//再进入倒这个循环有可能线程2抢到这个执行权//线程2要往下执行输出语句 ticket50 打印50if (ticket 0) {//线程具有抢占式的运行//咱们有没有可能线程3进入到if语句//此时线程1也进入到if语句了//线程3去打印 卖出了50张票//在线程1里面 ticket50//线程3又抢到ticket-- 又进入到循环了 ticket 49//线程3又抢到了ticket-- 又进入倒循环 ticket48//线程1又抢到资源要执行执行输出语句 tiekct50System.out.println(Thread.currentThread().getName() 卖出了第 ticket 票);ticket--;} else {System.out.println(买完了);break;//终止循环}}}
}
public class Demo1 {public static void main(String[] args) {MySync mySync new MySync();//这三个线程Thread thread1 new Thread(mySync, 线程1);thread1.start();Thread thread2 new Thread(mySync, 线程2);thread2.start();Thread thread3 new Thread(mySync, 线程3);thread3.start();}
} 解决方案 1.同步方法:使用一个关键字synchronized修饰方法。因为Java对象都有一个内置的锁对象。当使用这个关键字的时候修饰方法的时候这个方法就会被锁保护起来被锁锁住 当一个线程进来以后会立马锁住当前的方法。意味着只有一个线程进来其他线程都在外面等着。 public synchronized void run () {}package com.qfedu.c_sync;//最理想的状态
//先线程1进入到ticket50,循环 循环结束以后 此时
//tiket49了
//循环第二次的时候 线程2抢到资源了 此时ticket49
//循环 打印49 tiket-- ticket48了
//循环第三次的时候 线程2 抢到资源了 此时ticket48
//打印卖第48张票。ticket-- tiket47
//线程1又抢到循环
//现在的情况是有可能两个线程同时进入到while循环
//
class MySync1 implements Runnable {int ticket 50;//对这个run方法加了锁 就意味着只有一个线程进入到run方法中//其他线程都在run方法外面等待Overridepublic synchronized void run() {//while (true) {//死循环//两个线程都进入到了循环了//此时两个线程所持有的ticket 都是50//但是两个线程都要往下执行//有可能线程1 先执行了sout(50) 线程2在等待哦//线程1执行了--操作并出了循环 线程1ticket 49//线程1又抢到循环了 sout(49) tiket--//再进入倒这个循环有可能线程2抢到这个执行权//线程2要往下执行输出语句 ticket50 打印50if (ticket 0) {//线程具有抢占式的运行//咱们有没有可能线程3进入到if语句//此时线程1也进入到if语句了//线程3去打印 卖出了50张票//在线程1里面 ticket50//线程3又抢到ticket-- 又进入到循环了 ticket 49//线程3又抢到了ticket-- 又进入倒循环 ticket48//线程1又抢到资源要执行执行输出语句 tiekct50System.out.println(Thread.currentThread().getName() 卖出了第 ticket 票);ticket--;} else {System.out.println(买完了);break;//终止循环}}}
}
public class Demo2 {public static void main(String[] args) {MySync1 mySync new MySync1();//这三个线程Thread thread1 new Thread(mySync, 线程1);thread1.start();Thread thread2 new Thread(mySync, 线程2);thread2.start();Thread thread3 new Thread(mySync, 线程3);thread3.start();//为啥都是线程1卖出去的票//很巧 线程1抢到执行权了进入到run方法中//线程2和线程3在外面等着。//一个循环进来以后把循环全部执行完//会出现一家独大的情况也是不符合咱们生活场景的//咋解决咱们 不能方法中加锁在其他地方加锁}
} 换另外一种解决方法: 同步代码块:就是拥有了synchronized 关键字修饰一个语句块。被修饰的语句块会被加锁。从而实现同步。 语法格式: synchronized (this) {被加锁的代码块
}package com.qfedu.c_sync;//最理想的状态
//先线程1进入到ticket50,循环 循环结束以后 此时
//tiket49了
//循环第二次的时候 线程2抢到资源了 此时ticket49
//循环 打印49 tiket-- ticket48了
//循环第三次的时候 线程2 抢到资源了 此时ticket48
//打印卖第48张票。ticket-- tiket47
//线程1又抢到循环
//现在的情况是有可能两个线程同时进入到while循环
//
class MySync2 implements Runnable {int ticket 500;//对这个run方法加了锁 就意味着只有一个线程进入到run方法中//其他线程都在run方法外面等待Overridepublic void run() {//能不能对循环加锁不能 因为循环加锁以后还是一个线程循环完没有任何意义while (true) {//死循环//if语句加了锁以后//就意味着只有一个线程进入到if语句//假如线程1进入if语句了线程2和线程3就会等待//线程1打印50 并-- ticket变量为49//线程2抢到了49 sout(49) tiket-- 48//其他线程再抢//核心业务 加了锁只让一个线程进入操作完以后。锁释放掉//然后这三个线程再抢。还只能进一个再操作核心业务synchronized (this) {//只能让一个线程进入操作其他线程在外面等待排队if (ticket 0) {//线程具有抢占式的运行//咱们有没有可能线程3进入到if语句//此时线程1也进入到if语句了//线程3去打印 卖出了50张票//在线程1里面 ticket50//线程3又抢到ticket-- 又进入到循环了 ticket 49//线程3又抢到了ticket-- 又进入倒循环 ticket48//线程1又抢到资源要执行执行输出语句 tiekct50System.out.println(Thread.currentThread().getName() 卖出了第 ticket 票);ticket--;} else {System.out.println(买完了);break;//终止循环}}}}
}
public class Demo3 {public static void main(String[] args) {MySync2 mySync new MySync2();//这三个线程Thread thread1 new Thread(mySync, 线程1);thread1.start();Thread thread2 new Thread(mySync, 线程2);thread2.start();Thread thread3 new Thread(mySync, 线程3);thread3.start();//为啥都是线程1卖出去的票//很巧 线程1抢到执行权了进入到run方法中//线程2和线程3在外面等着。//一个循环进来以后把循环全部执行完//会出现一家独大的情况也是不符合咱们生活场景的//咋解决咱们 不能方法中加锁在其他地方加锁}
} 针对于同步代码块举个例子 上厕所的时候有坑位这个坑位就是资源。 三个人去抢这个资源如果不加锁的话会出现问题的?是的。加上锁以后就会保证数据准确性。 案例
加锁的目的为了保证数据的准确性。
卖电影票三个线程:淘票票美团猫眼100张票package com.qfedu.c_sync;class SaleTicket implements Runnable {//声明一个变量票//静态的变量和对象没有关系了private static int ticket 100;Overridepublic void run() {//美团while (true) {//美团 猫眼 淘票票synchronized (this) {if (ticket 0) {//淘票票 和猫眼同时进入到if语句但是都没有执行ticket--这个操作System.out.println(Thread.currentThread().getName() 卖出了第 ticket 票);//所以会打印 淘票票 100 猫眼100ticket--;} else {System.out.println(卖完了);break;}}}}
}
public class Demo4 {public static void main(String[] args) {SaleTicket saleTicket new SaleTicket();new Thread(saleTicket, 淘票票).start();new Thread(saleTicket, 美团).start();new Thread(saleTicket, 猫眼).start();//淘票票卖出了第100票//猫眼卖出了第100票//淘票票卖出了第99票//淘票票卖出了第97票//淘票票卖出了第96票//淘票票卖出了第100票//淘票票卖出了第99票//猫眼卖出了第98票//猫眼卖出了第97票}
}
线程就是这样不可控制但是可以加锁。让他可控制。