A:进程:
进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
B:线程:
线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
C:简而言之:
一个程序运行后至少有一个进程,一个进程中可以包含多个线程
线程实现
实现的两种方式
继承Thread
public class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName()+":"+i); } }}
测试类
public class MyThread02 extends Thread { @Override public void run() { MyThread t=new MyThread();//直接创建对象就能创建一个线程 t.start(); }}
实现Runnable
public class MyThreadImp implements Runnable{ int num; public MyThreadImp(int num){ this.num=num; } @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+num++); } }}
测试类
public class Test01 { public static void main(String[] args) { MyThreadImp mt=new MyThreadImp(10); Thread t=new Thread(mt); t.setName("张三"); t.start(); Thread t1=new Thread(mt); t1.setName("李四"); t1.start(); }}
多线程安全问题
线程的安全性==数据的安全性
①是否存在多线程
②是否有共享数据
③是否有多条语句执行共享数据
解决办法 synchronized同步锁
eg:
public class MyThread implements Runnable { int tickets; public MyThread(int tickets) { this.tickets = tickets; } Object o = new Object(); @Override public void run() { while (true) { synchronized (o) { if (tickets > 1) { System.out.println(Thread.currentThread().getName() + "-" + tickets--); } } } }}
测试类
MyThread mt=new MyThread(100); Thread t=new Thread(mt); t.setName("窗口1"); Thread t2=new Thread(mt); t2.setName("窗口2"); Thread t3=new Thread(mt); t3.setName("窗口3"); t.start(); t2.start(); t3.start();
如果不给线程加锁 则会产生数据乱掉,可能会产生-1;结果我们不可预测。
在方法中给加锁,另一种方法则是给方法加锁eg:
public class MyThread01 implements Runnable{ static int tickets=100; public MyThread01(int tickets) { this.tickets = tickets; } @Override public void run() { while (true) { method01(); } } private synchronized void method01() { if (tickets >= 1) { System.out.println(Thread.currentThread().getName() + "-" + tickets--); } }}
抢红包案列:
public class MyThread implements Runnable { int money; int count; public MyThread(int money, int count) { this.money = money; this.count = count; } @Override public void run() { // 产生一个随机数 method(); } private synchronized void method() { if (count > 1 && money != 0) { Random r = new Random(); double d = (r.nextInt(money) + 1); money -= d; System.out.println(Thread.currentThread().getName() + ":" + d); count--; } else { System.out.println(Thread.currentThread().getName() + ":" + money); } }}
测试类
public class Hongbao { public static void main(String[] args) { MyThread mt=new MyThread(10,3); Thread t=new Thread(mt); t.setName("张三"); t.start(); t.setPriority(10); Thread t1=new Thread(mt); t1.setName("李四"); t1.start(); Thread t2=new Thread(mt); t2.setName("李"); t2.start(); }}
生产消费者模式:
解释了多线程唤醒机制(notify()是Object中的方法)
使用多线程中的案列
产品 由于只是做测试使用 没有写全
public class Student { String name; int age; boolean flag;}
生产者 如果消费者没有消费产品 则进行等待 ,只有消费了生产者才会进行生产
public class StThread implements Runnable { private Student s; public StThread(Student s) { this.s = s; } int x; @Override public void run() { while (true) { synchronized (s) { if (s.flag) {//如果flag=true;则说明已经有对象了 还没有消费,则进行等待 try { s.wait(); } catch (InterruptedException e) { e.printStackTrace(); }// 等待 } if (x % 2 != 0) { s.name = "赵云"; s.age = 44; } else { s.name = "张飞"; s.age = 22; } x++; s.flag=true;//修改标记 s.notify();//唤醒 } } }}
消费者 如果消费者没有东西消费 则会进行等待 有了东西,才会进行消费
public class GtThread implements Runnable { private Student s; public GtThread(Student s) { this.s = s; } @Override public void run() { while (true) {//保证一直在等待中 synchronized (s) { if (!s.flag) {//flag=false则进行等待 等待学生对象的产生 try { s.wait();//线程等待 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(s.name + ":" + s.age); s.flag=false; s.notify(); } } }}
测试类
public class Test { public static void main(String[] args) { Student s=new Student(); StThread st=new StThread(s); GtThread gt=new GtThread(s); Thread t1=new Thread(st); Thread t2=new Thread(gt); t1.start(); t2.start(); }}
输出结果
输出结果:赵云:44张飞:22赵云:44张飞:22赵云:44张飞:22赵云:44.......一直交替循环下去
线程的生命周期