【Java高级】多线程基础

您所在的位置:网站首页 java多线程教程视频 【Java高级】多线程基础

【Java高级】多线程基础

2023-03-21 14:57| 来源: 网络整理| 查看: 265

文章目录 1.jvm启动时的线程2. 实现线程2.1实现线程的第一种方式2.2 实现线程第二种方法 3.线程生命周期4.线程名字5.线程的sleep6.终止线程的睡眠7.合理终止一个线程8.多线程安全问题8.1 概述8.2 模拟两个用户对同一个账户取款 8.3 同步代码块synchronized9.哪些变量存在线程安全问题10 synchronized三种写法11开发中解决线程安全问题

1.jvm启动时的线程

当中dos窗口输入

java HelloWrold

回车时,会先启动JVM,JVM就是一个进程,JVM会启动一个主线程调用main方法,和一个垃圾回收线程回收垃圾。

进程A和进程B不共享内存。 线程A 和线程B ,堆内存和方法区共享,栈区不共享。

分析下面程序有几个线程:

package com.sdnu.cpu; public class ThreadTest01 { public static void main(String[] args) { System.out.println("main method begin"); m1(); System.out.println("main method over"); } public static void m1(){ System.out.println("m1 method begin"); m2(); System.out.println("m2 method over"); } public static void m2(){ System.out.println("m2 method begin"); m3(); System.out.println("m3 method over"); } public static void m3(){ System.out.println("m3 method execute"); } }

只有一个,因为只有一个主栈。

2. 实现线程 2.1实现线程的第一种方式

一个类直接继承java.lang.Thread,重写run方法。

package com.sdnu.thread; import java.lang.Thread; public class ThreadTest02 { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); for(int i = 0; i " + i); } } } class MyThread extends Thread{ @Override public void run(){ for(int i = 0; i " + i); } } }

在这里插入图片描述 start方法的作用是启动一个分支线程,在JVM中开辟一个新的栈空间,只要开辟了新的内存空间,这个start方法就结束了,线程就启动了。

2.2 实现线程第二种方法

编写一个可运行的类实现Runnable类,实现run方法。 以一个可运行的类创建的对象传入Thread的构造方法中,构造Thread对象 Thread对象start即可。

package com.sdnu.thread; import java.lang.Runnable; public class ThreadTest03 { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread t = new Thread(myRunnable); t.start(); for(int i = 0; i " + i); } } } class MyRunnable implements Runnable{ @Override public void run() { for(int i = 0; i " + i); } } }

在这里插入图片描述

3.线程生命周期

在这里插入图片描述

4.线程名字

获取线程名字

String name = 线程对象.getName();

修改线程名字

线程对象.setName("线程名字");

获取当前线程

Thread currentThread = Thread.currentThread(); 5.线程的sleep

让当前进程进入休眠状态。

package com.sdnu.thread; public class ThreadTest06 { public static void main(String[] args) { for(int i = 0; i " + i); try { Thread.sleep(5 * 1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }

每隔5s输出一次

在这里插入图片描述

6.终止线程的睡眠 package com.sdnu.thread; public class ThreadTest08 { public static void main(String[] args) { MyRunnable2 myRunnable2 = new MyRunnable2(); Thread t = new Thread(myRunnable2); t.setName("t"); t.start(); //希望主线程5s后醒来 try { Thread.sleep(1000 * 5); } catch (InterruptedException e) { e.printStackTrace(); } t.interrupt(); } } class MyRunnable2 implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "---->" + "begin"); try { //休息一年 Thread.sleep(1000 * 60 * 60 * 24 * 365); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "---->" + "over"); } }

在这里插入图片描述

7.合理终止一个线程 package com.sdnu.thread; public class ThreadTest10 { public static void main(String[] args) { MyRunnable3 r = new MyRunnable3(); Thread t = new Thread(r); t.setName("t"); t.start(); //停留5s try { Thread.sleep(1000 * 5); } catch (InterruptedException e) { e.printStackTrace(); } r.run = false; } } class MyRunnable3 implements Runnable{ boolean run = true; @Override public void run() { for(int i = 0; i System.out.println(Thread.currentThread() + "---->" + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } else { return; } } } } 8.多线程安全问题 8.1 概述

什么时候数据在多线程并发的环境下存在安全问题?

条件1:多线程并发条件2:有共享数据条件3:有共享数据的修改问题

解决方案:线程同步机制

异步编程模型 vs 同步编程模型 在这里插入图片描述

8.2 模拟两个用户对同一个账户取款

Account

package com.sdnu.threadsafe; /** * 银行账户 */ public class Account { // 账户 private String actno; // 余额 private double balance; public Account() { } public Account(String actno, double balance) { this.actno = actno; this.balance = balance; } public String getActno() { return actno; } public void setActno(String actno) { this.actno = actno; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } // 取款的方法 public void withdraw(double money){ //取款之前的余额 double before = this.getBalance(); //取款之后的余额 double after = before - money; //模拟网络延迟 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //更新余额 this.setBalance(after); } } package com.sdnu.threadsafe; public class AccountThread extends Thread{ //两个线程共享同一个账户对象 private Account act; // 通过构造方法传递过来账户对象 public AccountThread(Account act){ this.act = act; } public void run(){ double money = 5000; act.withdraw(money); System.out.println(Thread.currentThread().getName() + "对" + act.getActno() + "取款成功,余额为" + act.getBalance() ); } }

测试

package com.sdnu.threadsafe; public class test { public static void main(String[] args) { Account account = new Account("act-001", 10000); Thread t1 = new AccountThread(account); Thread t2 = new AccountThread(account); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); } }

出现问题: 在这里插入图片描述

8.3 同步代码块synchronized public void withdraw(double money){ synchronized(this){ //取款之前的余额 double before = this.getBalance(); //取款之后的余额 double after = before - money; //模拟网络延迟 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //更新余额 this.setBalance(after); } }

在这里插入图片描述

9.哪些变量存在线程安全问题

成员变量在堆区,存在线程安全问题。 静态变量在方法区,存在线程安全问题。 局部变量不存在线程安全问题。

10 synchronized三种写法

在这里插入图片描述

11开发中解决线程安全问题

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3