JAVA基础【多线程】史上最简单基础入门01
前言:
在介绍多线程之前,先给大家普及下什么是进程,什么是线程。以及我们生活当中使用的那些软件使用到了多线程。
本文主线:
本文 从什么是进程,什么是线程。以及生活当中的多线程应用,前面的这些作为后面讲解什么是多线程的铺垫。主要介绍基本的并发,并行。以及如何创建多线程。
目录
基础铺垫
什么是 进程,线程?
进程
是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多 个进程;
进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创 建、运行到消亡的过程。
线程
线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。
一个进程 中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程
生活中用到的多线程软件
以联想电脑管家为例,左边每一个功能都是一个单独的线程。也就是每个功能直接的运行时独立的,互不影响。
在运行加速清理的时候,仍然可以去进行杀毒。
间接入门
简介:
上面介绍了什么是进程,什么是线程。以及在生活当中使用的多线程软件。下面开始进入今天的主题 “多线程”
并发与并行
并发:指两个或多个事件在同一个时间段内发生。
并行:指两个或多个事件在同一时刻发生(同时发生)。
创建线程
创建线程有两种方式,一种直接继承Thread类。还有一种实现.Runnable接口。
不过.Runnable接口只有一个run方法,没有开始方法。还得借助Thread类的Start方法执行,直接把.Runnable的实现对象传到Thread的构造函数里。
Theard
package itheima.demo01.getName;
/*
* 线程名称:
* 主线程:main
* 新线程:Thread-0,Thread-1
* */
public class Demo01GetThreadName {
public static void main(String[] args) {
//创建Thread类的子类对象
MyThread mt=new MyThread();
//给线程设置名称
mt.setName("kang");
//调用start方法,开启新线程,执行run方法
mt.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new MyThread().start();
new MyThread().start();
//视频进度:threadl类的常用方法,开头
}
}
myTheard类
package itheima.demo01.getName;
/*
* 获取线程的名称
* 1.使用Thread类中的方法getName()
* String getName()
* 返回该线程的名称。
* 2.可以先获取当前正在执行的线程,使用线程的方法geName()获取线程名称
* static Thread currenThread();
* */
//定义为Thread类的子类
public class MyThread extends Thread{
//重写Thread类中的run方法,设置线程
@Override
public void run() {
//获取线程名称
System.out.println(currentThread());
// String name = getName();
// System.out.println(name);
}
}
Runable
这个和下面的买票案例一样(同一个案例),就是这个没有做线程安全。这个会出现两个线程买同一张票,或者出现不存在的票比如-1 (具体请看下面结果)
package itheima.demo06.ThreadSafe;
/*
* 模拟买票案例
* 创建三个线程,同时开启,对共享的票进行出售
*
* */
public class Demo01Ticket {
public static void main(String[] args) {
//实例化接口实现类
RunnableImpl ticket0=new RunnableImpl();
//实例化Thread类,把接口类对象传进构造参数里
Thread th=new Thread(ticket0);
Thread th1=new Thread(ticket0);
Thread th2=new Thread(ticket0);
//开启线程
th.start();
th1.start();
th2.start();
}
}
买票Runable接口实现类
package itheima.demo06.ThreadSafe;
/*
* 实现Runable接口:实现买票案例
* */
public class RunnableImpl implements Runnable {
//定义一个多线程共享的票源
private int ticket=100;
@Override
public void run() {
//使用死循环,让买票操作重复执行
while (true){
//判断是否有票
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,买票ticker...
System.out.println(Thread.currentThread().getName()+"----->正在买票"+ticket+"张票");
ticket--;
}
}
}
}
结果:
Theard和.Runnable的区别
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
总结:
实现Runnable接口比继承Thread类所具有的优势:
1. 适合多个相同的程序代码的线程去共享同一个资源。
2. 可以避免java中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
入门完毕
买票案例
package itheima.demo07.Synchranized;
/*
* 模拟买票案例
* 创建三个线程,同时开启,对共享的票进行出售
*
* */
public class Demo01Ticket {
public static void main(String[] args) {
//实例化接口实现类
RunnableImpl ticket0=new RunnableImpl();
//实例化Thread类,把接口类对象传进构造参数里
Thread th=new Thread(ticket0);
Thread th1=new Thread(ticket0);
Thread th2=new Thread(ticket0);
//开启线程
th.start();
th1.start();
th2.start();
}
}
买票Runable接口实现类
package itheima.demo07.Synchranized;
/*
* 实现Runable接口:实现买票案例
* 第一种锁解决方案
* */
public class RunnableImpl implements Runnable {
//定义一个多线程共享的票源
private int ticket=100;
//创建一个锁对象
Object obj=new Object();
@Override
public void run() {
//使用死循环,让买票操作重复执行
while (true){
//同步代码块
synchronized (obj){
//判断是否有票
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,买票ticker...
System.out.println(Thread.currentThread().getName()+"----->正在买票"+ticket+"张票");
ticket--;
}
}
}
}
}
结果:
这个案例使用到了同步代码块,也就是synchronized线程同步的概念。(线程同步的三种用法,下一篇博客介绍。)