Java线程学习

  • 一、创建的线程几种方法:

①通过实现Runnable接口
public class ThreadDemo{
    public static void main(String [] args) {
        TestThread t=new TestThread();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }
}
class TestThread implements Runnable {
    int i=100;
    public void run(){
        while(true) {
            if (i > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i--;
                System.out.println(Thread.currentThread().getName() + 
                " is selling ticket " + i);
            }
            else {
                break;
            }
        }
    }
}

结果:

Thread-0 is selling ticket 99
Thread-1 is selling ticket 98
·
·
·
Thread-2 is selling ticket 5
Thread-0 is selling ticket 4
Thread-1 is selling ticket 3
Thread-3 is selling ticket 2
Thread-2 is selling ticket 1
Thread-0 is selling ticket 0
Thread-1 is selling ticket -1
Thread-3 is selling ticket -2
Thread-2 is selling ticket -3

解释:
1.通过new Thread( new TestThread【实现了Runnable接口的类】)的形式创建线程
2.特殊地,类似上文的形式。将TestThread t=new TestThread()单独写出来,在其后可一次性创建和开始多个线程。 TestThread内普通变量在不同线程中共享
但是由于线程之间没有加锁限制,结果有103行,多了3行

②通过继承Thread类
public class ThreadDemo
{
    public static void main(String [] args)
    {
        new TestThread().start();
        new TestThread().start();
        new TestThread().start();
        new TestThread().start();
    }
}
class TestThread extends Thread
{
    private static int i=100;  //static变量是共享的,所有的线程共享
    public void run()
    {
        while(true)
        {
            if(i>0)
            {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                System.out.println(Thread.currentThread().getName() + i);
                i = i - 1;
            }
            else
            {
                break;
            }
        }
    }
}

结果:

Thread-1 is selling ticket 100
Thread-0 is selling ticket 99
Thread-3 is selling ticket 98
·
·
·
Thread-0 is selling ticket 5
Thread-2 is selling ticket 4
Thread-1 is selling ticket 3
Thread-3 is selling ticket 2
Thread-0 is selling ticket 1
Thread-2 is selling ticket 0
Thread-1 is selling ticket -1
Thread-3 is selling ticket -2

解释:
1. 直接通过new ThreadTest【继承了类Thread的类】.start()创建并开始线程
2. 普通变量之间无共享,只有ThreadTest类的变量声明为static才能实现共享

  • 另:变量共享相关

例子,无volatile,非共享。

public class tryThread {
    public static void main(String args[]){
        TestThread th=new TestThread();
        Thread t1 = new Thread(th);
        Thread t2 = new Thread(th);
        Thread t3 = new Thread(th);
        t1.start();
        t2.start();
        t3.start();
        try{
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        th.flag=false;
        System.out.println("main is exiting");
    }
}
class TestThread implements Runnable{
    boolean flag = true;
    public void run() {
        while (flag) {
        }
        System.out.println("Thread is exiting");
    }
}

结果:
main is exiting
无限循环,需要自行终止程序。
(结果只输出一行主线程退出时的提示语句,而子线程一直在while循环里,没有检测到 flag 已经变化,也没有输出子线程退出时的提示语句)

注意:这里特别将run方法中的while循环写的很简单,因为太复杂会迷之检测到 flag 的变化,从而结束线程,得到Thread is exiting的正确结果

要让编译器来不及反应到flag的变化(大雾)


更 新 : 百 度 之 后 , 发 现 原 因 可 能 是 之 前 写 的 代 码 里 有 非 原 子 级 别 的 操 作 , 例 如 n + + , n = n + 1 , 可 能 类 似 v o l a t i l e 失 效 问 题 。 ( v o l a t i l e 失 效 问 题 详 情 见 下 ) \color{red}{更新:百度之后,发现原因可能是之前写的代码里有非原子级别的操作,例如n++,n=n+1,可能类似volatile失效问题。(volatile失效问题详情见下)} n++n=n+1volatilevolatile


  • 实现变量共享的方法:
  1. 若线程是实现Runnable接口而来,则可使用volatile关键字
    即在关键变量前,即boolean flag前加volatile
volatile boolean flag

结果:
main is exiting
Thread is exiting
Thread is exiting
Thread is exiting
正确退出了

特别注意:volatile的失效问题,即当用volatile关键字修饰的变量n进行n++,n=n+1等非原子级别操作时,volatile会失效。
  1. 如果线程是继承Thread类而来,关键变量前使用static
  • 变量共享中的一些问题
  1. 工作缓存副本
    见上文用volatile或static实现
    再次提醒:注意volatile失效问题
  2. 关键步骤加锁限制
    synchronized互斥加锁 (通用方法,简单但负担高)
    防止多个线程访问同一个关键数据产生错误。【本文开头第一段代码多出3行的原因】

注意:一个线程访问synchronized代码块时。另一个线程可访问程序的非synchronized部分

  • ⑴synchronized修饰函数
public class tryThread {
    public static void main(String args[]){
        TestThread th=new TestThread();
        Thread t1 = new Thread(th);
        Thread t2 = new Thread(th);
        Thread t3 = new Thread(th);
        t1.start();
        t2.start();
        t3.start();
        try{
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        th.flag=false;
        System.out.println("main is exiting");
    }
}
class TestThread implements Runnable{
    boolean flag = true;
    String str="";
    public void run() {
             while (flag) {
                 fun();
             }
        System.out.println("Thread is exiting");
    }
    private synchronized void fun() {
    }
}

结果:
main is exiting
Thread is exiting
Thread is exiting
Thread is exiting
正确输出。

  • ⑵synchronized修饰代码块
String str="";
synchronized (str) {
    fun();
}
③线程池

一个线程必有所属线程组
待续……

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值