Java多线程笔记

*/

public class MyThreatTest {

public static void main(String[] args) {

TestMyThread t1 = new TestMyThread();

t1.start();

new Thread(){

@Override

public void run(){

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

if (i%2==0){

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + “子线程” + i);

yield();

}

}

}

}.start();

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

if (i%3==0){

System.out.println(Thread.currentThread().getName() + “main方法” + i);

}

if (i==20){

try {

t1.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

class TestMyThread extends Thread{

@Override

public void run(){

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

if (i%5==0){

System.out.println(Thread.currentThread().getName() + “2222222222222子线程” + i);

}

}

}

}

synchronized锁机制

一把锁只能同时被一个线程获取,没有获得锁的线程只能等待;

每个实例都对应有自己的一把锁(this),不同实例之间互不影响;例外:锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象公用同一把锁

synchronized修饰的方法,无论方法正常执行完毕还是抛出异常,都会释放锁

##同步代码—Runnable接口方式

/**

*方式一:同步代码块

  • synchronized(同步监视器){

  •      //需要被同步的代码
    
  • }

  • 说明:

  • 1.操作共享数据的代码,即为需要被同步的代码

  • 2.共享数据:多个线程共同操作的变量

  • 3.同步监视器,俗称:锁。任何一个类的对象都可以作为索

  • 4.在Java中,我们通过同步机制,来解决线程的安全问题。

  • 补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。

  • 方式二:同步方法

  • 如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。

  • 5.同步的方式,解决了线程的安全问题。—好处

  • 操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。

*/

public class WindowToRunnable {

public static void main(String[] args) {

Window2 window2 = new Window2();

Thread t1 = new Thread(window2);

Thread t2 = new Thread(window2);

Thread t3 = new Thread(window2);

t1.setName(“窗口1”);

t2.setName(“窗口2”);

t3.setName(“窗口3”);

t1.start();

t2.start();

t3.start();

}

}

class Window2 implements Runnable{

//这里不用加static,因为调用的对象只有一个

private int ticket=100;

@Override

public void run() {

while (true) {

synchronized (this.getClass()){

if (ticket > 0) {

// try {

// Thread.sleep(100);

// } catch (InterruptedException e) {

// e.printStackTrace();

// }

System.out.println(Thread.currentThread().getName() + “买票,票号:” + ticket);

ticket–;

}

}

}

}

}

同步方法–Runnable接口方法


package com.atguigu.juc.bookPage;

/**

  • 使用同步方法解决实现Runnable接口的线程安全问题

  • 关于同步方法的总结:

  • 1.同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。

  • 2.非静态的同步方法,同步监视器是: this

  • 静态的同步方法,同步监视器是:当前类本身

*/

public class WindowExtSynn {

public static void main(String[] args) {

Window4 w1 = new Window4();

Window4 w2 = new Window4();

Window4 w3 = new Window4();

w1.setName(“窗口1”);

w2.setName(“窗口2”);

w3.setName(“窗口3”);

w1.start();

w2.start();

w3.start();

}

}

class Window4 extends Thread{

private static int ticket=100;

@Override

public void run() {

while (true){

show();

}

}

private static synchronized void show() {

if (ticket>0){

System.out.println(Thread.currentThread().getName()+“:买票:票号为”+ticket);

ticket–;

}

}

}

##同步方法—继承方法

package com.atguigu.juc.bookPage;

/**

  • 使用同步方法解决实现Runnable接口的线程安全问题

  • 关于同步方法的总结:

  • 1.同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。

  • 2.非静态的同步方法,同步监视器是: this

  • 静态的同步方法,同步监视器是:当前类本身

*/

public class WindowExtSynn {

public static void main(String[] args) {

Window4 w1 = new Window4();

Window4 w2 = new Window4();

Window4 w3 = new Window4();

w1.setName(“窗口1”);

w2.setName(“窗口2”);

w3.setName(“窗口3”);

w1.start();

w2.start();

w3.start();

}

}

class Window4 extends Thread{

private static int ticket=100;

@Override

public void run() {

while (true){

show();

}

}

private static synchronized void show() {

if (ticket>0){

System.out.println(Thread.currentThread().getName()+“:买票:票号为”+ticket);

ticket–;

}

}

}

##死锁

示例:两个线程都拿到第一层锁的key,然后都需要第二层锁的key,但key在对方手中,而方法没有执行完,都不可能释放key,互相僵持。

import static java.lang.Thread.sleep;

public class TestSyn {

public static void main(String[] args) {

StringBuffer s1 = new StringBuffer();

StringBuffer s2 = new StringBuffer();

new Thread(){

@Override

public void run() {

synchronized (s1) {

s1.append(“a”);

s2.append(“1”);

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (s2) {

s1.append(“b”);

s2.append(“2”);

System.out.println(s1);

System.out.println(s2);

}

}

}

}.start();

new Thread(new Runnable() {

@Override

public void run() {

synchronized (s2) {

s1.append(“c”);

s2.append(“3”);

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (s1) {

s1.append(“d”);

s2.append(“4”);

System.out.println(s1);

System.out.println(s2);

}

}

}

}).start();

}

}

##Lock锁机制

import java.util.concurrent.locks.ReentrantLock;

/**

  • 解决线程安全问题的方式三: Lock锁— JDK5.0新增

  • synchronized 与Lock的异同?

  • 相同:二者都可以解决线程安全问题

  • 不同: synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器

  •  Lock需要手动的启动同步(Lock() ),同时结束同步也需要手动的实现(unlock())
    

*/

public class LockTest {

public static void main(String[] args) {

Window6 window6 = new Window6();

Thread t1 = new Thread(window6);

Thread t2 = new Thread(window6);

Thread t3 = new Thread(window6);

t1.setName(“窗口1”);

t2.setName(“窗口2”);

t3.setName(“窗口3”);

t1.start();

t2.start();

t3.start();

}

}

class Window6 implements Runnable{

private int ticker=100;

private ReentrantLock lock=new ReentrantLock();

@Override

public void run() {

while (true){

lock.lock();

try {

if (ticker>0){

System.out.println(Thread.currentThread().getName()+“买票:票号:”+ticker);

ticker–;

}else {

break;

}

} finally {

lock.unlock();

}

}

}

}

银行有一个账户。 有两个储户分别向同一个账户存3000元,每次存1e00,存3次。每次存完打印账户余额。最新面试资料宝典

/**

  • 银行有一个账户。

  • 有两个储户分别向同一个账户存3000元,每次存1e00,存3次。每次存完打印账户余额。

  • 分析:

  • 1.是否是多线程问题?是,两个储户线程

  • 2.是否有共享数据?有,账户(或账户余额).

  • 3.是否有线程安全问题?有

  • 4.需要考虑如何解决线程安全问题?同步机制:有三种方式。

*/

public class AccountTest {

public static void main(String[] args) {

Account account = new Account(0);

Customer c1 = new Customer(account);

Customer c2 = new Customer(account);

c1.setName(“A”);

c2.setName(“B”);

c1.start();

c2.start();

}

}

class Account{

private double balance;

public Account(double balance) {

this.balance = balance;

}

//存钱

public synchronized void deposit(double amt){

//synchronized (this.getClass()) {

if (amt>0){

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

balance+=amt;

System.out.println(Thread.currentThread().getName()+“存钱成功,余额为”+balance);

}

// }

}

}

class Customer extends Thread{

private Account acc;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
…(img-1m4eaEQU-1712123741881)]

[外链图片转存中…(img-ezIVk90d-1712123741882)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

[外链图片转存中…(img-WjKIErIJ-1712123741882)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值