java中的线程和多线程

   线程

 1.概念

程序:一个可执行的文件

进程:一个正在运行的程序,也可以理解为在内存中开辟了一块空间

线程:负责程序的运行,可以看做一条执行的通道或执行单元,所以我们经常将进程的工作理解成线程的工作

问题1:进程中可不可以没有线程?

答:不可以,进程中必须有线程,至少有一个.当有一个线程的时候我们称为单线程(唯一的线程就是主线程).

当有一个以上的线程同时存在的时候我们称为多线程.

多线程的作用:为了实现同一时间干多件事情.

任务区:我们将有线程工作的地方叫做任务区.

每个线程都有一个任务区,任务区通过对应的方法产生作用.

问题2:JVM(java虚拟机)默认是多线程吗?

答:至少有两个线程:

1.主线程:任务区-main函数

2.垃圾回收线程:任务区-finalize函数

public class Demo9 {
	public static void main(String[] args) {
		new Test();
		
		//手动执行gc方法,运行垃圾回收器,触发垃圾回收机制
		/*
		 * 原理:当执行gc的时候,会触发垃圾回收机制,开启垃圾回收线程,调用finalize()方法.
		 * 注意点:多个线程之间是抢CPU的关系,线程之间有随机性.
		 */
		System.gc();
		//当执行到这里的时候,正常情况下有两个线程:主线程和垃圾回收线程
		System.out.println("main");
	}//线程是随着任务的开始而开始结束而结束.只要任务没有结束,线程就不会结束.当线程还在工作的时候,进程没有办法结束.
}

class Test{
	/*
	 * finalize()方法应该由系统调用,为了模拟多线程的环境,我们将它进行了重写
	 * 正常情况下,当Test类的对象被释放的时候,finalize方法会被自动调用.
	 * @see java.lang.Object#finalize()
	 */
	protected void finalize() throws Throwable {
		System.out.println("finalize()");
	}
}

2.线程的创建

默认情况下,JNM有主线程和垃圾回收线程,但它们都是有系统创建的,为了完成我们自己的任务,就要创建自己的线程

java将程序面向对象了,形成的类就是面向对象类,在Thread类内部完成的工作的任务区就是run方法.

注意点:如果想让run作为任务区,必须通过start方法,让run自动执行,不能手动调用.

public class Demo {
/*	public static void main(String[] args) {//一共两个线程.一个主线程,一个垃圾回收线程.但是一般先暂时忽略垃圾回收线程
		//1.通过Thread类直接创建线程
		Thread thread1 = new Thread();//创建了一个线程
		Thread thread2 = new Thread();//创建了一个线程
		
		//2.调用start方法
		thread1.start();//两个线程,忽略垃圾回收线程
		thread2.start();//三个线程
		
		System.out.println("main");
	}*/
	public static void main(String[] args) {//一共两个线程.一个主线程,一个垃圾回收线程.但是一般先暂时忽略垃圾回收线程
		//1.通过Thread类的子类创建线程
		MyThread thread1 = new MyThread("bingbing");//创建了一个线程
		MyThread thread2 = new MyThread("yingying");//创建了一个线程
		
		//2.调用start方法
		thread1.start();//两个线程,忽略垃圾回收线程
		thread2.start();//三个线程
		
		System.out.println("main");
		for(int i = 0;i < 10;i++){
			System.out.println(Thread.currentThread().getName()+"   run:main"+"i:"+i);
		}
		
		/*
		 * 手动调用run方法:它只是一个普通方法,不代表任务区,只有被自动调用的时候才代表任务区
		 * 手动调用时:在哪里调用的这行代码,run方法内部就代表哪个线程.
		 */
		//thread1.run();
	}
}

//创建Thread类的子类
class MyThread extends Thread{
	String myname;
	
	public MyThread(String myname) {
		super();
		this.myname = myname;
	}

	/*
	 *重写run方法--作为任务区,完成我们自己的功能
	 *Thread.currentThread():获取的是当前进程
	 *.getName():是系统给的名字
	 */
	public void run() {
		for(int i = 0;i < 10;i++){
			System.out.println(Thread.currentThread().getName()+"   run:"+myname+"  i:"+i);
		}
	}
}

线程创建方式一(用继承Thread类的方式创建子类)

例如:创建四个售票员,同时卖票.得到线程名字和票数.

public class Demo {
	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 = 20;
	@Override
	public void run() {
		for(int i = 0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+"  i:"+i+" "+--num);
		}
	}
}

线程创建方式二:线程与任务分离(常用方式!)

public class Demo{
	public static void main(String[] args) {
		//1.先创建一个任务类对象
		Ticket ticket = new Ticket();
		
		//2.创建线程并绑定任务
		/*
		 * 如果我们自己创建了独立的任务类,线程会优先调用我们手动传入的任务类的run方法,不会再去调用Thread类默认的run方法
		 */
		Thread thread1 = new Thread(ticket);
		Thread thread2 = new Thread(ticket);
		Thread thread3 = new Thread(ticket);
		Thread thread4 = new Thread(ticket);
		
		//开启线程
		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
	}
}

//创建任务类
class Ticket implements Runnable{
	//因为Ticket对象被4个线程共享,所以num也被共享
    int num = 40;
	public void run() {
		for(int i = 0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+"  i:"+i+" "+--num);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35334203/article/details/81738681