一.程序
程序是一段静态的代码,它是应用软件执行的蓝本
二.进程
进程是程序的一次动态执行过程,它对应从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。如果把银行一天的工作比作一个进程,那么早上打上班铃是进程的开始,晚上打下班铃是进程的结束。
三.线程
线程是比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身产生、存在和消亡的过程,也是一个动态的概念。就像银行一天的工作开始后,可以有多个不同的“线程”为客户服务,如财会部门,出纳部门,保安部门等。我们知道,每个进程都有一段专用的内存区域,与此不同的是,线程间可以共享相同的内存单元(包括代码与数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。比如在银行一天的工作开始后,财会部门、出纳部门、保安部门这三个线程共享银行的电力资源,财会部门、出纳部门可能共享银行的账目数据等。多线程的程序能更好地表达和解决现实世界的具体问题,是计算机应用开发和程序设计的一个必然发展趋势。
当然重点还是线程
下面进行代码解释:
单线程
//这是一个类
public class Demo01MainThread {
public static void main(String[] args) {
Person p1=new Person("小强");
p1.run();
//System.out.println(0/0);//这行代码会报错,因为分母不能为0,所以程序就会从次中断,后面的代码将无法执行(单线程的缺点)
Person p2=new Person("旺财");
p2.run();
}
}
//这是一个类
public class Person {
private String name;
public void run(){
//定义循环,执行20次
for (int i=0;i<20;i++){
System.out.println(name+"-->"+i);
}
}
public Person(String name) {
this.name = name;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建多线程的第一种方式
//这是一个类
public class Demo01Thread {
public static void main(String[] args) {
//3.创建Thread类的子类对象
MyThread mt=new MyThread();
//4.调用Thread类中的方法,start方法,开启新的线程,执行run方法
mt.start();
for (int i=0;i<20;i++){
System.out.println("main:"+i);
}
}
}
//这是一个类
//1.创建一个Thread类的子类
public class MyThread extends Thread{
//2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
@Override
public void run() {
for (int i=0;i<20;i++){
System.out.println("run:"+i);
}
}
}
多线程原理_随机打印的结果(接着上面的代码)
多线程原理_多线程内存图解
Thread类的常用方法_获取线程名称
//定义一个Thread类的子类
public class MyThread extends Thread {
//重写Thread类中的run方法,设置线程任务
@Override
public void run() {
//获取线程的名称
//String name = getName();
//System.out.println(name);
//Thread t = Thread.currentThread();
//System.out.println(t);
//String name = t.getName();
//System.out.println(name);
//链式编程
System.out.println(Thread.currentThread().getName());
}
}
//
public class Demo01GetThreadName {
public static void main(String[] args) {
//创建Thread类的子类对象
MyThread mt=new MyThread();
//调用start方法,开启新线程,执行run方法
mt.start();
new MyThread().start();
new MyThread().start();
//链式编程
System.out.println(Thread.currentThread().getName());
}
}
Thread类的常用方法_设置线程的名称
//
public class MyThread02 extends Thread{
public MyThread02(){
}
public MyThread02(String name){
super(name);//把线程名称传递给父类。让父类(Thread)给子线程起一个名字
}
@Override
public void run() {
//获取线程的名称
System.out.println(Thread.currentThread().getName());
}
}
//
public class Demo01SetThreadName {
public static void main(String[] args) {
//开启多线程
MyThread02 mt=new MyThread02();
mt.setName("小强");
mt.start();
//开启多线程
new MyThread02("旺财").start();
}
}
创建多线程的第二种方法
//
public class Demo01Runnable {
public static void main(String[] args) {
//3.创建一个Runnable接口的实现类对象
RunableImpl run=new RunableImpl();
//4.创建一个Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t=new Thread(run);
//5.调用Thread类中的start方法,开启新的线程执行run方法
t.start();
for (int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
}
//
//1.创建一个Runnable接口的实现类
public class RunableImpl implements Runnable{
//2.在实现类中重写Runnable接口的run方法,设置线程任务
@Override
public void run() {
for (int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
}
匿名内部类来创建线程
public class DemoInnerClassThread {
public static void main(String[] args) {
//线程的父类是Thread
//new MyThread().start
new Thread(){
//重写run方法,设置线程任务
@Override
public void run() {
for (int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName()+"-->"+"孙佳驰");
}
}
}.start();
//线程的接口Runnable
//Runnable r=new RunnableImpl();//多态
Runnable r = new Runnable() {
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + "程序员");
}
}
};
new Thread(r).start();
//简化接口方式
new Thread(new Runnable() {
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + "程序员2");
}
}
}).start();
}
}
线程安全问题的概述
线程安全问题的代码实现(这里的代码是有线程安全问题的问题代码)
//这是一个类
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();
}
//票存在,买票 ticket--
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
ticket--;
}
}
}
}
//这是一个类
public class Demo01Ticket {
public static void main(String[] args) {
//创建一个Runnable接口的实现类对象
RunnableImpl run=new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t0=new Thread(run);
Thread t1=new Thread(run);
Thread t2=new Thread(run);
//调用start方法开启多线程
t0.start();
t1.start();
t2.start();
}
}
线程安全问题产生的原理
解决线程安全问题_同步代码块
//这是一个类
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();
}
//票存在,卖票 ticket--
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
ticket--;
}
}
}
}
}
//这是一个类
public class Demo01Ticket {
public static void main(String[] args) {
//创建一个Runnable接口的实现类对象
RunnableImpl run=new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t0=new Thread(run);
Thread t1=new Thread(run);
Thread t2=new Thread(run);
//调用start方法开启多线程
t0.start();
t1.start();
t2.start();
}
}
同步技术的原理
解决线程安全问题_同步方法
//
public class RunnableImpl implements Runnable {
//定义一个叫多个线程共享的票源
private int ticket=100;
//设置线程任务:买票
@Override
public void run() {
//使用死循环,让买票重复执行
while (true){
payTicket();
}
}
public synchronized void payTicket(){
//先判断票是否存在
if (ticket>0){
//提高安全问题的概率,让程序睡眠一下
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,买票 ticket--
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
ticket--;
}
}
}
//
public class Demo01Ticket {
public static void main(String[] args) {
//创建一个Runnable接口的实现类对象
RunnableImpl run=new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t0=new Thread(run);
Thread t1=new Thread(run);
Thread t2=new Thread(run);
//调用start方法开启多线程
t0.start();
t1.start();
t2.start();
}
}
解决线程安全问题_Lock锁
//
public class RunnableImpl implements Runnable {
//定义一个叫多个线程共享的票源
private int ticket=100;
//1.在成员位置创建一个ReentrantLock对象
Lock l=new ReentrantLock();
//设置线程任务:买票
@Override
public void run() {
//使用死循环,让买票重复执行
while (true){
//2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
l.lock();
//先判断票是否存在
if (ticket>0){
//提高安全问题的概率,让程序睡眠一下
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,买票 ticket--
System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
ticket--;
}
// 3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放取锁
l.unlock();
}
}
}
//
public class Demo01Ticket {
public static void main(String[] args) {
//创建一个Runnable接口的实现类对象
RunnableImpl run=new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t0=new Thread(run);
Thread t1=new Thread(run);
Thread t2=new Thread(run);
//调用start方法开启多线程
t0.start();
t1.start();
t2.start();
}
}
线程状态
等待唤醒案例
等待唤醒案例代码实现
public class Demo01WaitAndNotify {
public static void main(String[] args) {
//创建锁对象,保证唯一
Object obj=new Object();
//创建一个顾客线程(消费者)
new Thread(){
@Override
public void run() {
//保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
synchronized (obj){
System.out.println("告诉老板要的包子的种类和数量");
//调用wait方法,放弃cup的执行,进入到WAITING状态(无限等待)
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒之后执行的代码
System.out.println("包子已经做好了,开吃");
}
}
}.start();
//创建一个老板线程(生产者)
new Thread(){
@Override
public void run() {
//花5秒做包子
try {
Thread.sleep(5000);//花五秒钟做包子
} catch (InterruptedException e) {
e.printStackTrace();
}
//保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
synchronized (obj){
System.out.println("老板5秒钟之后做好包子,告知顾客,可以吃包子了");
obj.notify();
}
}
}.start();
}
}
Object类中wait带参方法和notif
public class Demo02WaitAndNotify {
public static void main(String[] args) {
//创建锁对象,保证唯一
Object obj=new Object();
//创建一个顾客线程(消费者)
new Thread(){
@Override
public void run() {
//保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
synchronized (obj){
System.out.println("顾客1告诉老板要的包子的种类和数量");
//调用wait方法,放弃cup的执行,进入到WAITING状态(无限等待)
try {
obj.wait(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒之后执行的代码
System.out.println("包子已经做好了,顾客1开吃");
}
}
}.start();
//创建一个顾客线程(消费者)
new Thread(){
@Override
public void run() {
//保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
synchronized (obj){
System.out.println("顾客2,告诉老板要的包子的种类和数量");
//调用wait方法,放弃cup的执行,进入到WAITING状态(无限等待)
try {
obj.wait(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒之后执行的代码
System.out.println("包子已经做好了,顾客2开吃");
}
}
}.start();
//创建一个老板线程(生产者)
new Thread(){
@Override
public void run() {
//花5秒做包子
try {
Thread.sleep(5000);//花五秒钟做包子
} catch (InterruptedException e) {
e.printStackTrace();
}
//保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
synchronized (obj){
System.out.println("老板5秒钟之后做好包子,告知顾客,可以吃包子了");
//obj.notify();//如果有多个等待线程,随机唤醒一个
obj.notifyAll();//唤醒所有等待的线程
}
}
}.start();
}
}



