程序,进程,线程,多线程概念
package com.qianfeng.test;
/*
* 多线程:
*
* 程序:是一个可执行文件。
* 进程:是一个正在运行的程序,在内存中开辟了一块空间。
* 线程:负责程序的运行,可以看作是程序运行的一条通道或者一个执行单元。所以我们通常将进程的工作理解成线程的工作。
*
* 进程中可不可以没有线程?
* --必须有线程,至少有一个,当(一个进程)有一个线程存在的时候,我们称为单线程,这个唯一的线程就是主线程。
* 当(一个进程)有一个以上的线程存在的时候,我们称为多线程。
*
* 多线程存在的意义:为了实现同一时间做多件事情。
*
* 任务区:我们将线程完成工作的方法称为任务区。每一个线程都有自己的任务区。
*
* JVM是多线程吗?
* 一定是多线程。
* 至少有两个
* 主线程的任务区:main方法
* 垃圾回收线程任务区:finalize()方法(该方法在Object类里)
*
*
*/
public class Demo7 {
public static void main(String[] args) {//一个main线程
new Test();
/*
* 手动执行gc方法,运行垃圾回收器,触发垃圾回收机制,
* 工作原理:执行gc方法,触发垃圾回收机制,运行垃圾回收线程,调用finalize()方法
*
* 多个线程是抢cpu的关系,cup有随机性。
*/
System.gc();//两个:主线程和垃圾回收线程
System.out.println("main");
}//线程是随着任务的开始而开始结束而结束,只要任务没有结束线程就不会结束。当线程还在工作的时候,进程没有办法结束。
}
class Test{
/*
* finalize()方法应该由系统调用,为了模拟多线程的使用环境,我们将它进行重写。
* 正常情况下,当Test类的对象被释放时,这个方法就会被调用。
*/
@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
}
}
Thread创建线程
package com.qianfeng.test;
/*
* 自己创建线程的原因:系统的线程无法完成我们自己的功能,我们就自己创建线程,系统将线程面向对象了,形成的类就是Thread。
* Thread的任务区是run()方法,
* 注意:如果想让run方法作为任务区,不能手动去调用,必须通过调用start方法,让run自动执行。
* 两种创建线程的方式:
*/
public class Demo8 {
// public static void main(String[] args) {//为了方便研究,暂时忽略垃圾回收线程,认为这里有一个主线程--main线程
// //1.通过Thread直接创建线程
// //创建两个线程
// Thread thread1 = new Thread();
// Thread thread2 = new Thread();
//
// //通过start方法让线程工作
// thread1.start();
// thread2.start();//有三个线程,两个子线程
//
// System.out.println("main");
//
// }
public static void main(String[] args) {//为了方便研究,暂时忽略垃圾回收线程,认为这里有一个主线程--main线程
//1.通过Thread的子类直接创建线程
//创建两个线程
Thread thread1 = new MyThread("bingbing");//thread-0
Thread thread2 = new MyThread("yingying");//thread-1
//通过start方法让线程工作
thread1.start();
thread2.start();//有三个线程,两个子线程
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+" "+" i:"+i);
}
/*
* 当手动调用run()时,run变成了普通方法,失去了任务区的功能。
* run内部对应的线程就是run方法被手动调用的位置对应的线程。
*/
thread1.run();
}
}
class MyThread extends Thread{
String myname;
public MyThread(String myname) {
super();
this.myname = myname;
}
@Override
public void run() {
/*
* Thread.currentThread():获取的当前线程
* Thread.currentThread().getName():获取的是当前线程的名字,系统给的名字。
*/
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+" "+myname+" i:"+i);
}
}
}
创建多线程的两种方式:Thread类的子类、Runnable
package com.qianfeng.test;
/*
* 创建的第一种方式:通过创建Thread类的子类--让run留在了线程的内部,造成任务与线程的绑定,操作不方便。
* 第二种方式:让线程与任务分离--将run从线程中独立出来。好处:操作更方便,哪个线程想工作,我就把任务交给谁。
*
* 实例:实现四个售票员售票
* 分析:创建4个线程--4个售票员
* 任务:只需要一个
* 数据:只需要一个
*
* 第一种方式:不方便,逻辑不清晰
*
*/
//public class Demo2 {
//
// public static void main(String[] args) {
//
// //创建线程对象
// Seller seller1 = new Seller();
// Seller seller2 = new Seller();
// Seller seller3 = new Seller();
// Seller seller4 = new Seller();
//
// //开启线程
// seller1.start();
// seller2.start();
// seller3.start();
// seller4.start();
//
//
// }
//}
//
//class Seller extends Thread{
//
// static int num =40;//为了实现num的共享
// @Override
// public void run() {
// for (int i= 0; i < 10; i++) {
// System.out.println(Thread.currentThread().getName()+" i:"+i+" "+ --num);
// }
// }
//}
//第二种:线程与任务分离
public class Demo2 {
public static void main(String[] args) {
//创建任务对象
Ticket ticket = new Ticket();
//创建线程对象并关联同一个任务
//如果我们创建了自己独立的任务类,线程会优先调用我们手动传入线程的任务类对象的run方法,不会再去调用Thread默认的run方法。
Thread seller1 = new Thread(ticket);
Thread seller2 = new Thread(ticket);
Thread seller3 = new Thread(ticket);
Thread seller4 = new Thread(ticket);
//开启线程
seller1.start();
seller2.start();
seller3.start();
seller4.start();
}
}
//创建任务类
class Ticket implements Runnable{
//因为Ticket对象被四个线程共享,所以num作为属性也被共享了。
int num =40;
public void run() {
for (int i= 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+" i:"+i+" "+ --num);
}
}
}