目录
一,程序,进程,线程理解
1) 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
2)进程(process)是程序的一次执行过程, 或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。
➢如:运行中 的QQ,运行中的MP3播放器
➢程序是静态的,进程是动态的
➢进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域
3)线程(thread),进程可进一步细化为线程,是一个程序内部的一条执行路径。
➢若一个进程同一时间并行执行多个线程,就是支持多线程的
➢线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
➢一个进程中的多个线程共享相同的内存单元/内存地址空间→它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全的隐患。
二,创建多线程的方法
方式一:
继承与Thread类
* 1,创建一个继承与Thread类的子类
* 2,重写Thread类的run()方法将此线程执行的操作声明在run()方法体中
* 3,创建子类对象
* 4,通过此对象调用start()方法
public class ChuangJianFangShi1 {
//1,创建一个继承与Thread类的子类
static class MyThread extends Thread {
//如果有变量(属性)后面需要共享需要加static
//2,重写Thread类的run()方法将此线程执行的操作声明在run()方法体中
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}
public static void main(String[] args) {
//标准方法
/* // 3,创建子类对象
MyThread myThread = new MyThread();
//4,通过此对象调用start()方法
myThread.start();*/
//匿名方法
new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}.start();
}
}
方式二:
实现Runnable接口
public class ChuangJianFangShi2 {
//例买票窗口,没有考虑线程安全问题
//1,创建一个实现Runnable接口的类
static class Window implements Runnable{
private int num = 100;//如果用第一种方法要加static
//2,实现类实现Runnable接口中的抽象方法
@Override
public void run() {
while (true){
if (num > 0){
System.out.println(Thread.currentThread().getName() + "票号为" + num);
num--;
}else {
break;
}
}
}
}
public static void main(String[] args) {
//3,创建实现类对象
Window window = new Window();//如果用第一种方法需要创多个对象
//4,将此对象作为参数传递到Thread类的构造器中,创建Thread类对象
Thread t1 = new Thread(window);
Thread t2 = new Thread(window);
Thread t3 = new Thread(window);
//设置线程名字
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
//5,通过Thread类的对象调start方法
t1.start();
t2.start();
t3.start();
}
}
方式三:
实现Callable接口
方式四:
使用线程池
三,Thread类常用方法
* Thread类中的方法 * start():启动当前线程,调用run()方法 * run():通常需重写 * currentThread():静态方法,返回执行当前代码的线程(Thread.currentThread.其他类中的方法) * getName():获取当前线程名字 * setName():设置当前线程名字 * yield():释放当前线程执行权 * join:满足当前线程执行条件停止执行执行其他一个线程其他一个线程执行完毕后在执行当前线程 * 理解2::在线程a中调用线程b的join方法,此线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态、 *sleep():静态方法可以直接用类去调:让当前线程睡眠指定的毫秒数在 * isAlive():判断当前线程是否还存活 * 如何获取和设置线程的优先级 * 在线程名字后面+Thread.currentThread().getPriority() *在start()方法之前设置调用方法setPriority()
四,线程安全与通信
出现原因:当某个线程操作时,还没完成,其他线程就参与进来了,也进行操作 解决:当某个线程操作时,还没完成,就阻止其他线程参与进来了
解决方法:
方法一:同步代码快 * synchronized(同步监视器){ * 需要被同步的代码 * } * 说明:操作共享数据的代码及为需要被同步的代码 * 共享数据:多个线程共同操作的变量 * 同步监视器:俗称锁,可以是任何一个类的对象,都可以充当锁 * 例如:Object obj = new Object(); 继承方式要加static: static Object obj = new Object(); * 要求:多个线程必须要共同用同一把锁 * 实现方式:this * 继承方式:类.class * * 方法二:同步方法 * 把需要被同步的代码写成一个方法然后在run()方法里调用 * * 方法三:Lock锁
线程通信 * wait();一个线程进来阻塞一下,实现多个线程交替工作 * notify(); * notifyAll();解除阻塞,实现多个线程交替工作 * 是定义在Obj类中的方法 * 必须使用在同步代码块或同步方法中的同步监视器。lock解决线程安全时不能用
public class XianChengAnQuan {
//例买票窗口,考虑线程安全问题,实现多个线程交替工作分配均匀
//1,创建一个实现Runnable接口的类
static class Window implements Runnable{
//Object object = new Object();
//static Object object = new Object(); :如果用继承的方法需要这样写
private int num = 100;//如果用第一种方法要加static
//2,实现类实现Runnable接口中的抽象方法
@Override
public void run() {
while (true){
synchronized (this){//如果用继承的方法:类.class
notifyAll();//解除阻塞,实现多个线程交替工作
if (num > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "票号为" + num);
num--;
try {
wait();//一个线程进来阻塞一下,实现多个线程交替工作
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
break;
}
}
}
}
}
public static void main(String[] args) {
//3,创建实现类对象
Window window = new Window();//如果用第一种方法需要创多个对象
//4,将此对象作为参数传递到Thread类的构造器中,创建Thread类对象
Thread t1 = new Thread(window);
Thread t2 = new Thread(window);
Thread t3 = new Thread(window);
//设置线程名字
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
//5,通过Thread类的对象调start方法
t1.start();
t2.start();
t3.start();
}
五,消费者与生产者案例
package com.bdqn.lianxi.duoxaincheng.xiaofeizheshengcanzhe;
public class DianYuan {
private int num = 0;
//生产产品
public synchronized void shengcan(){
if (num < 20){
num++;
System.out.println(Thread.currentThread().getName() + "开始生产第" + num + "个产品");
notify();
}else {
//等待
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public synchronized void xaiofei(){
if (num > 0){
System.out.println(Thread.currentThread().getName() + "开始消费第" + num + "个产品");
num--;
notify();
}else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.bdqn.lianxi.duoxaincheng.xiaofeizheshengcanzhe;
public class ShengChanZhe extends Thread{
private DianYuan dianYuan;
public ShengChanZhe(DianYuan dianYuan) {
this.dianYuan = dianYuan;
}
@Override
public void run() {
System.out.println(getName() + "开始生产品");
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dianYuan.shengcan();
}
}
}
package com.bdqn.lianxi.duoxaincheng.xiaofeizheshengcanzhe;
public class XiaoFeiZhe extends Thread{
private DianYuan dianYuan;
public XiaoFeiZhe(DianYuan dianYuan) {
this.dianYuan = dianYuan;
}
@Override
public void run() {
System.out.println(getName() + "开始消费产品");
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dianYuan.xaiofei();
}
}
}
package com.bdqn.lianxi.duoxaincheng.xiaofeizheshengcanzhe;
public class Test {
public static void main(String[] args) {
DianYuan dian = new DianYuan();
ShengChanZhe sheng = new ShengChanZhe(dian);
sheng.setName("生产者一");
XiaoFeiZhe xiao = new XiaoFeiZhe(dian);
xiao.setName("消费者一");
sheng.start();
xiao.start();
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
package com.bdqn.lianxi.duoxaincheng.work;
public class Run implements Runnable{
private int num = 10;
private boolean isTrue = false;
@Override
public void run() {
while (!isTrue){
people();
}
}
public synchronized void people(){
if (num == 0){
isTrue = true;
return;
}
notify();
System.out.println(Thread.currentThread().getName() + "号选手拿到接力棒");
num--;
for (int i = 0;i < 10;i++ ){
System.out.println(Thread.currentThread().getName() + "号选手跑了" + (i + 1) * 10 + "米");
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Run run = new Run();
Thread thread = new Thread(run);
Thread thread1 = new Thread(run);
Thread thread2 = new Thread(run);
Thread thread3 = new Thread(run);
thread.setName("1");
thread1.setName("2");
thread2.setName("3");
thread3.setName("4");
thread.start();
thread1.start();
thread2.start();
thread3.start();
}
}