*/
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–;
}
}
}
}
}
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开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/4429f072a19453258ae78561b1917d30.jpeg)
完结
Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。
Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
…(img-1m4eaEQU-1712123741881)]
[外链图片转存中…(img-ezIVk90d-1712123741882)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/4429f072a19453258ae78561b1917d30.jpeg)
完结
Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。
Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。
[外链图片转存中…(img-WjKIErIJ-1712123741882)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!