提到多线程,就得提提什么是线程,什么是进程,什么是程序了
如下图所示:
下面是cpu:
a)单核CPU,其实是一种假的多线程,因为在一个时间单元内,也只能执行一个线程的任务。例如:虽然有多车道,但是收费站只有一个工作人员在收费,只有收了费才能通过,那么CPU就好比收费人员。如果有某个人不想交钱,那么收费人员可以把他“挂起”(晾着他,等他想通了,准备好了钱,再去收费)。但是因为CPU时间单元特别短,因此感觉不出来。
b)如果是多核的话,才能更好的发挥多线程的效率。(现在的服务器都是多核的)c)一个Java应用程序java.exe,其实至少有三个线程:main0主线程,gc0垃圾回收线程,异常处理线程。当然如果发生异常,会影响主线程。
下面是并发和并行:
并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。
并发:一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事
以单核CPU为例,只使用单个线程先后完成多个任务(调用多个方法),肯定比用多个线程来完成用的时间更短,为何仍需多线程呢?
1.提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
2.提高计算机系统CPU的利用率
3.改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
多线程的应用场景:
~程序需要同时执行两个或多个任务。
~程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。
~需要一些后台运行的程序时
线程创建有两种方式
1.创建线程的第一种方式
创建类继承Thread类
覆写run()方法,run方法就等于是新线程中的main方法,是程序执行的起点和终点
启动线程手动调用当前线程对象的start)方法不是run方法
如下图:
下面是源码:
package day_20_Test;
/*
public class Homework_02 {
public static void main(String[] args) { //main方法中创建三个线程 Thread t1 = new CreateThread(); Thread t2 = new CreateThread(); Thread t3 = new CreateThread(); //启动 t1.start(); t2.start(); t3.start(); }
}
//单例类
class SingLeton{
//单例模式构造方法需要私有化
private SingLeton(){
super();
}
//饿汉模式,什么时候创建对象什么时候赋值 private static SingLeton obj = null; //用户想要创建对象,需要用我们提供的方法,因为需要多线程安全,所以这里加上synchronized public synchronized static SingLeton createObj(){ if(obj == null){ obj = new SingLeton(); obj.printObj(); return obj; } else{ System.out.println("拿到已有对象"); return obj; } } //写一个成员方法打印输出,测试是否创建对象 public void printObj(){ System.out.println(this); } @Override public String toString() { return "这是单例模型的一个对象"; }
}
//继承thread类的创建线程类
class CreateThread extends Thread{
@Override public void run() { //在这里面调用方法创建对象 SingLeton.createObj(); }
}
2.创建线程的第二种方式
实现Runnable接口,覆写run方法
启动线程调用Thread的start方法
下面是源码:
package day_20_Test;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
*/
public class Homework_03 {
public static void main(String[] args) throws InterruptedException { //起两个线程 Thread t1 = new Thread(new CreateThread2()); Thread t2 = new Thread(new CreateThread2()); t1.setName("线程1"); t2.setName("线程2"); t1.start(); t2.sleep(500); t2.start(); }
}
//下面是实现接口的创建线程类
class CreateThread2 implements Runnable{
//声明一个整型共享数组sharearrays
public static int sharearrays[] = new int[6];
//定义一个成员变量,来保存一个线程一共运行几次 private int count; public void run() { for (int i = 0 ; i<6 ; i++ ){ //创建锁对象 Lock lock = new ReentrantLock(); //加锁,锁内数据只能一个线程执行 lock.lock(); try { //添加数据 addNumber(i); System.out.println(Thread.currentThread().getName()+"添加"+(count+1)+"次"); }finally{ //解锁 lock.unlock(); } //为了防止一个线程直接完成,这里睡眠随机数长的时间 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //计数值+1 count++; //当计数值达到3跳出 if(count >= 3){ return; } } //count等于0,1,2执行,否则跳出 //因为每个线程为数组提供三个数据,所以在线程中肯定需要判断是否够三个 } //写一个生成随机数的方法,返回值为int型 private static int createRandom(){ //写一个随机数,先写个从1到10的吧 Random random = new Random(); return random.nextInt(10)+1; } //定义一个往数组中添加数据的方法 private void addNumber(int i){ sharearrays[i] = createRandom(); System.out.println("添加的数据值为"+sharearrays[i]); }
}
以上就是今天学习比较深刻的理解了,希望能对查询到这篇文章的朋友有帮助,以及自己日后可以继续查看。