浅谈Java多线程机制

浅谈java多线程机制

一、线程和进程

1. 概念的区别

线程:程序执行的路径
进程:内存中运行的程序

在这里插入图片描述
注意:进程是内存中实实在在的内存空间,而线程则是程序运行时的不同路径只在一个内存空间内存在。

2.线程的调度

  1. 分时调度:所有线程轮流占用CPU的使用权,平均分配使用时间到每个线程。
  2. 抢占式调度(Java所使用):优先让优先级高的线程使用CPU,如果线程的优先级相同,则随机选择线程。
    使用setPriority​(int newPriority)更改线程的优先级(!但不是一定的 ,我测试过很多情况并不能根据优先级的设置进行执行

二、同步与异步(并发与非并发)

1.概念

  1. 同步是类似排队的额执行→效率低但安全→线程安全
  2. 异步是同时执行→效率高但不安全→非线程安全

三、实现

→继承自Thread

package com.jiansheng;
/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        t1.start();
        t2.start();
        t3.start();
        /*for (int i=0;i<=10;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
        }*/
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());
    }
}

每个线程有用自己的栈空间 但共同享有堆空间

→实现Runnable(常用且推荐使用)

  1. 创建一个Runnable对象也就是任务
  2. 创建一个线程,并非配Runnable任务
  3. 线程.start()执行
package com.jiansheng;
/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable());
        Thread t2 = new Thread(new MyRunnable());
        Thread t3 = new Thread(new MyRunnable());
        t1.start();
        t2.start();
        t3.start();
        /*for (int i=0;i<=10;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
        }*/
    }
}
class MyRunnable implements Runnable{
    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());
    }
}

优点:避免extends Thread时单继承的局限;任务和线程分离 更便于理解思想和程序的健壮性;最重要的是线程池技术只接受Runnable类型的任务

四、线程的Thread类详解

1. sleep()方法
让当前线程睡眠,可传入设定睡眠时间参数(毫秒)
直接用Thread.sleep()

package com.jiansheng;
/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable());
        t1.start();
    }
}
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <= 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }
}

五、线程的特点

1. 线程的阻塞:所有消耗时间的操作导致线程在某处等待,就叫做线程的阻塞。
2.线程的中断

  • 一个线程是一条独立的路径,是否中断应该由线程自身来决定 而不应该使用stop()方法强制中断。
  • 通常做法是给线程打标记,告诉线程应该中断了,然后线程接收到标记信息后,决定是否中断。
package com.jiansheng;
/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable());
        t1.start();
        for (int i = 0; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
        t1.interrupt();

    }
}
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <= 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("我被通知中断了,执行中断。");
                break;
            }
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }
}

六、线程的安全和不安全

经典卖票逻辑

要解决卖票时的逻辑问题 要使用排队的逻辑
1.解决方案1:
使用同步代码块(隐式锁)

package com.jiansheng;
/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(mr);
        t1.setName("窗口1");
        Thread t2 = new Thread(mr);
        t2.setName("窗口2");
        Thread t3 = new Thread(mr);
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}
class MyRunnable implements Runnable{
    int count = 10;
    Object o = new Object();
    @Override
    public void run() {
        while(true){
            synchronized (o){
                if (count>0){
                    System.out.println("开始卖票");
                    count--;
                    System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余"+count+"张。");
                    if (count==0){
                        System.out.println("票已卖光。");
                        break;
                    }
                }
            }
        }
    }
}

2.解决方案2
使用同步方法(隐式锁)

package com.jiansheng;
/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(mr);
        t1.setName("窗口1");
        Thread t2 = new Thread(mr);
        t2.setName("窗口2");
        Thread t3 = new Thread(mr);
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}
class MyRunnable implements Runnable{
    int count = 10;
    Object o = new Object();
    @Override
    public void run() {
        while(true){
            if(sale()==false){
                break;
            }
        }
    }
    public synchronized boolean sale(){
            if (count>0){
                System.out.println("开始卖票");
                count--;
                System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余"+count+"张。");
                if (count==0){
                    System.out.println("票已卖光。");
                }
                return true;
            }
            return false;
    }
}

3.使用显式锁
推荐使用显式锁,因为思想逻辑上更清晰。

package com.jiansheng;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Jiansheng
 */
public class Demo1 {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(mr);
        t1.setName("窗口1");
        Thread t2 = new Thread(mr);
        t2.setName("窗口2");
        Thread t3 = new Thread(mr);
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}
class MyRunnable implements Runnable{
    int count = 10;
    Object o = new Object();
    Lock l =new ReentrantLock();
    @Override
    public void run() {
        while(true){
            l.lock();
                if (count>0){
                    System.out.println("开始卖票");
                    count--;
                    System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余"+count+"张。");
                    if (count==0){
                        System.out.println("票已卖光。");
                        break;
                    }
                }
            l.unlock();
        }
    }
}

Jiansheng

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值