【Java系列】【基础版】多线程基础

来源:互联网 发布:淘宝酷卡体育东西正嘛 编辑:程序博客网 时间:2024/06/03 20:19
  1. 多线程基础

1.1 认识进程和线程

1.1.1 什么是进程

    1.1.1.1 进程是正在进项的程序,是资源分配的一个基本单位,有内存分配;

1.1.2 什么是线程

    1.1.2.1 线程是进程的一个执行单位,也是进程的执行顺序; 

    1.1.2.2 一个进程至少有一个线程,可以由两个或以上的线程;

1.1.3 JVM至少有几个线程

    1.1.3.1 至少有一个或两个线程,main方法和垃圾回收线程;

1.1.4 什么是多线程

    1.1.4.1 2个或以上的线程去执行

1.1.5 多线程的作用

    1.1.5.1 提高效率,线程之间切换的小号是可以接受的;

    1.1.5.2 单线程容易阻塞;

    1.1.5.3 多个线程同时执行代码;

    1.1.5.4 一个线程挂了,还有其他的线程在,程序还在执行

1.1.6 进程和线程是谁创建的

    都是操作系统创建的

1.1.7 如何自定义一个线程

    1.1.7.1 继承Thread类,重写run方法

    1.1.7.2 生成对象

    1.1.7.3 开启start

1.1.8 所有实现的接口

    1.1.8.1 Runnable接口

    1.1.8.2 new线程对象的时候,创建了线程

    1.1.8.3 start方法,沟通了操作系统,告诉操作系统有一个线程要开启,也调用了run


1.2 代码示例

1.2.1 在main主线程里,再度开启其他线程

1.2.1.1 测试类:

public class Test {

public static void main(String[] args) throws ParseException  {

Test001 t = new Test001();//这里代表着产生了一个线程

Test001 t1 = new Test001();//这里代表着产生了一个线程

System.out.println("开启线程之前");

//t1.run();//代表着调用了对象的方法

t.start();//这里代表开启了一个线程,是沟通了操作系统

t1.start();//这里代表开启了一个线程,是沟通了操作系统

try {

Thread.sleep(15);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("开启线程之后");

System.out.println("main  over");

}

}

1.2.1.2 重写run方法类,继承Thread类:

class Test001 extends Thread{

@Override

public void run() {

for (int i = 0; i < 100; i++) {

try {

sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("run    .. "+i);

}

}

}



1.2.2 创建一个线程,和主程序交替执行

1.2.2.1 测试类

public class ThreadTest {

public static void main(String[] args) {

Test t = new Test();

t.start();

for (int i = 0; i < 10; i++) {

System.out.println("main>>>"+i);

}

System.out.println("main  -  gg");

}

}

1.2.2.2 方法类

class Test extends Thread{

int i = 0;

@Override

public void run() {

while(true){

if(i<10){

System.out.println("run方法..." + i++);

}else{

System.out.println("run  - OVER");

break;

}

}

}

}


1.2.3 模拟买票功能

1.2.3.1 测试类

public class TestRunnable01 {

public static void main(String[] args) {

Runnable x1 = new XinXiaoMi();

Thread t1 = new Thread(x1);

Thread t2 = new Thread(x1);

Thread t3 = new Thread(x1);

t1.setName("小红");

t2.setName("小蓝");

t3.setName("小绿");

t1.start();

t2.start();

t3.start();

}

}

1.2.3.2 方法类

class XinXiaoMi implements Runnable{

static int i =100;//共享的

Object o = new Object();

@Override

public void run() {

boolean b = true;

while(b){

synchronized (o) {

if(i>0){//i = 1

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"...卖出了手机,编号是..." + i--);

}

else{

break;

}

}

}

}

}


1.2.4 小明和老婆同时存钱,每次存取500元,每人存5次

1.2.4.1 测试类:

public class TestRunnable02 {

public static void main(String[] args) {

test t = new test();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

t1.setName("小明");

t2.setName("陈学冬");

t1.start();

t2.start();

}

}

1.2.4.2 方法类:

class test implements Runnable{

int con = 0;//初始定义了账户余额为0元

Object o = new Object();

@Override

public void run() {

synchronized (o) {

for (int i = 0; i < 5; i++) {

con += 500;

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"  存了500大洋---此时账户余额为  。。"+con);

}

}

}

}


1.2.4 小明和老婆同时存钱,每次存取500元,每人存5次; 同时实现方法的同步

1.2.4.1 测试类

public class TestM {

public static void main(String[] args) {

test00 t = new test00();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

t1.setName("小明");

t2.setName("baby");

t2.start();

t1.start();

}

}

1.2.4.2 方法类

class test00 implements Runnable{

int con = 0;//初始定义了账户余额为0元

Object o = new Object();

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+" 到达房间门口");

this.show();//一次就好,许你地老天荒

}

public synchronized void show(){

System.out.println(Thread.currentThread().getName()+" 锁住了房间");

for (int i = 0; i < 5; i++) {

con += 500;

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"  存入了500,此时余额是    "+con);

}

System.out.println(Thread.currentThread().getName()+" 离开了房间,打开了锁");

}

}


1.2.5 小明和老婆同时存钱,每次存取500元,每人存5次; 同时实现方法的同步;同时实现交替存储

1.2.5.1 测试类

public class TestM2 {

public static void main(String[] args) {

test000 t = new test000();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

t1.setName("小明");

t2.setName("baby");

t2.start();

t1.start();

}

}

1.2.5.2 方法类

class test000 implements Runnable{

int con = 0;//初始定义了账户余额为0元

Object o = new Object();

@Override

public void run() {

for (int i = 0; i < 5; i++) {

//等待区

show();

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public synchronized void show(){

System.out.println(Thread.currentThread().getName()+" 上锁了");

con += 500;

System.out.println(Thread.currentThread().getName()+"  存入了  500 ,  此时余额为   "+con);

System.out.println(Thread.currentThread().getName()+" 锁开了");

}

}


1.2.6 死锁的示例

1.2.6.1 测试类:

 /* Runnablere =new Runnable() {

public void run() {

}

};

 */

public class Test01 {

public static void main(String[] args) {

TestSY ts1 = new TestSY();

Thread th1 = new Thread(ts1);

Thread th2= new Thread(ts1);

th1.start();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

TestSY.b = false;

th2.start();

}

}


1.2.6.2 方法类:


class TestSY implements Runnable{

static boolean b = true;

Object o = new Object();

Object o1 = new Object();

@Override

public void run() {

if( b ){

synchronized (o) {

System.out.println("if  拿到了 o 的锁");

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (o1) {

System.out.println("if-----");

}

}

}else{

synchronized (o1) {

System.out.println("else  拿到了 o1 的锁");

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (o) {

System.out.println("else-----");

}

}

}

    }

}


1.3 cpu调度

    cpu的时间片,cpu控制着执行;

    cpu会自行分配资源给线程,得到资源的线程可以执行,没有得到资源的线程没有办法执行;

    多个cpu才是真正意义上的同时执行多线程,因为运行速度特别多,会给我们产生错觉,认为是同时执行的;


1.4 线程的状态

1.4.1 新生

    1.4.1.1 new对象的时候代表着新生;

1.4.2 就绪

    1.4.2.1 start方法代表着就绪,这个时候在等待着CPU的资源;如果有资源就进入执行状态,没有资源就继续等待;

1.4.3 执行

    1.4.3.1 拿到时间片,正在执行;时间片被拿走了就离开了执行状态;

1.4.4 阻塞

    1.4.4.1 睡觉sleep,让资源;时间结束了就回到就绪状态,等待资源;

1.4.5 死亡

    1.4.5.1 线程执行结束;非正常死亡方式;


1.5 两种创建线程方式的比较

1.5.1 继承方式创建简单,使用的方法也多;

1.5.2 java是单继承的,使用集成方式过于死板;

1.5.3 继承是不共享资源的,实现方式是共享的;

1.5.4 主要由于单继承的机制,推荐使用Runnable接口实现这种方式

    1.5.4.1 实现接口,重写方法

    1.5.4.2 new一个对象

    1.5.4.3 把new的对象放进线程(Thread)对象里

    1.5.4.4 用线程对象开启线程

    1.5.4.5 注意:run方法不能抛异常


1.6 同步代码块原理解析

    1.6.1 java提供了锁的机制synchronized ,可以锁住一段代码,在任何时期这段代码里面最多只有一个线程在执行。每个要进来的线程都会先判断此处有没有上锁。

1.6.1.1 如果没有,就进去并且上锁,再执行完之后才会离开,同时打开锁,其他的线程才可以进来

1.6.1.2 如果被锁,再门口等待,进不去; 这里锁,锁的是对象。具体锁那个对象呢。具体情况具体分析

    1.6.2 同步的优缺点

        1.6.2.1 同步的前提

            1.6.2.1.1 两个或两个以上的线程去操作共享数据时

        1.6.2.2 同步的好处

            1.6.2.2.1 保证了线程的安全性

        1.6.2.3 同步的缺陷

            1.6.2.3.1 消耗增加,但是影响不大

            1.6.2.3.2 使用不当容易造成死锁







































原创粉丝点击