myThread3.setName(“Thread1”);
//启动线程
myThread3.start();
//main线程
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " —> " + i);
}
}
}
class MyThread3 extends Thread{
public void run(){
//获取当前线程的名字
System.out.println(currentThread().getName());
for (int i = 0; i < 100; i++) {
System.out.println(currentThread().getName() + " —> " + i);
}
}
}
(二)
/*
-
关于线程的sleep()方法
-
1.静态方法
-
2.参数是毫秒
-
3.作用:让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其它线程使用
-
这行代码出现在A线程中,A线程就会进入休眠。
-
这行代码出现在B线程中,B线程就会进入休眠。
-
4.Thread.sleep()方法,可以做到这样的效果:
-
间隔特定的时间,去执行一段特定的代码,每隔多久执行一次
-
*/
public class ThreadTest05 {
public static void main(String[] args) {
/*//在main进程中,所以使用sleep方法,是使得main方法进入阻塞状态
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//五秒后执行此代码
System.out.println(“Hello World”);
*/
//使得每个一秒钟输出一个数字
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
}
/*
-
Thread.sleep()方法的面试题
-
*/
public class ThreadTest06 {
public static void main(String[] args) {
//创建线程对象
MyThread5 myThread = new MyThread5();
myThread.setName(“ttt”);
myThread.start();
//请问这会使得 myThread 休眠一秒吗
try {
myThread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//不会,因为sleep是一个静态方法,最终在编译器会看做Thread.sleep() 这个的作用是休眠当前线程
//当前线程是main线程
System.out.println(“Hello World”);
//Hello World
//0
//1
//2
//3
//4
}
}
class MyThread5 extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
}
(三)
/*
-
怎么唤醒正在休眠的线程?
-
不是终断线程的执行,是终止线程的睡眠
-
*/
public class ThreadTest07 {
public static void main(String[] args) {
//创建线程对象
Thread myThread6 =new Thread(new MyThread6());
myThread6.setName(“钢铁侠 Thread”);
myThread6.start();
//希望过5秒能让 myThread6 醒过来
//一年太长了
try {
//当前线程是主线程
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//这个方法是利用了异常处理
终止t线程的睡眠
myThread6.interrupt();
}
}
class MyThread6 implements Runnable{
@Override
public void run() {
//休眠一年
System.out.println(Thread.currentThread().getName() + " —> begin");
try {
Thread.sleep(365 * 24 * 60 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//一年之后再执行
System.out.println(Thread.currentThread().getName() + “—> over”);
}
}
(四)
//在java中怎么强行终止一个线程的执行
public class ThreadTest08 {
public static void main(String[] args) {
MyThread7 myThread7 =new MyThread7();
myThread7.setName(“美国队长 Thread”);
myThread7.start();
//过五秒后让 myThread7 终止
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread7.stop();//已过时,不建议使用
}
//stop存在缺点,容易丢失数据,因为直接将线程杀死了
//美国队长 Thread --> 0
//美国队长 Thread --> 1
//美国队长 Thread --> 2
//美国队长 Thread --> 3
//美国队长 Thread --> 4
}
class MyThread7 extends Thread{
public void run(){
for (int i = 0; i < 100; i++) {
//每个一秒输出一个数字
System.out.println(Thread.currentThread().getName() + " --> " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(五)
/*
-
怎么合理的终止一个线程的执行?
-
*/
public class ThreadTest09 {
public static void main(String[] args) {
MyThread8 myThread =new MyThread8();
Thread myThread8 = new Thread(myThread);
myThread8.setName(“黑豹”);
myThread8.start();
//模拟五秒
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//想什么时候关闭,什么时候讲run 变成false就行了
myThread.run = false;
}
}
class MyThread8 implements Runnable{
//布尔标记
boolean run = true;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (run){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}else{
//有什么要保存的在这保存
return;
}
}
}
}
(六)
//了解:关于线程的优先级
public class ThreadTest010 {
public static void main(String[] args) {
//线程的优先级
System.out.println(Thread.MAX_PRIORITY);//10
System.out.println(Thread.NORM_PRIORITY);//5
System.out.println(Thread.MIN_PRIORITY);//1
//将main线程的优先级变为1
Thread.currentThread().setPriority(1);
Thread myThread9 = new Thread(new MyThread9());
myThread9.setName(“蜘蛛侠”);
优先级较高的,只是抢到的CPU时间片相对多一些
myThread9.start();
for (int i = 0; i < 1000; i++) {
System.out.println(“main —>” + i);
}
}
}
class MyThread9 implements Runnable{
@Override
public void run() {
System.out.println("线程的默认优先级是 " + Thread.currentThread().getPriority());
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + “—>” + i);
}
}
}
(七)
/*
- 让位:
*当前线程暂停,回到就绪转态,让给其它线程
- static void yield() 静态方法*/
public class ThreadTest11 {
public static void main(String[] args) {
Thread myThread = new MyThread10();
myThread.setName(“雷神”);
myThread.start();
for (int i = 0; i < 1000; i++) {
System.out.println("main —> " +i);
}
}
}
class MyThread10 extends Thread{
public void run(){
for (int i = 0; i < 1000; i++) {
//每输出100就让位一次
if (i %100 == 0){
Thread.yield();//当前线程暂停一下,让给主线程
}
System.out.println(Thread.currentThread().getName() + "—> " + i);
}
}
}
(八)
/*
-
线程的合并
-
*/
public class ThreadTest12 {
public static void main(String[] args) {
System.out.println(“main begin!!!”);
Thread myThread11 = new MyThread11();
myThread11.setName(“黑寡妇”);
myThread11.start();
try {
//不是栈的合并,是栈之间的协调
myThread11.join();//myThread11 合并到 主线程,主线程进入阻塞状态,当 myThread11 执行完再执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“main over”);
}
//main begin!!!
//0
//1
//2
//3
//4
//main over
}
class MyThread11 extends Thread{
@Override
public void run() {
for (int i = 0; i <5 ; i++) {
System.out.println(i);
}
}
}
(一)模拟银行操作系统
public class Test {
public static void main(String[] args) {
//创建银行账户
Account account =new Account(“美国队长的账户”,10000);
//创建两个线程
//猎鹰和美国队长同时去取钱
AccountThread accountThread1 = new AccountThread(account);
AccountThread accountThread2 = new AccountThread(account);
accountThread1.setName(“美国队长”);
accountThread2.setName(“猎鹰”);
//取款
accountThread1.start();
accountThread2.start();
//猎鹰 对 美国队长的账户 取款了5000.0元,余额是 5000.0
//美国队长 对 美国队长的账户 取款了5000.0元,余额是 5000.0
//这就出错了
}
}
public class AccountThread extends Thread{
//同一个进程有相同的账号对象
//模拟两个人同时去ATM机器取钱
//has a
private Account account;
//构造方法,传入银行账户属性
public AccountThread(Account account) {
this.account = account;
}
@Override
//run方法的执行表示取款操作
public void run() {
//假设就取5000元钱
double money = 5000;
account.withdraw(money);
//取款信息
System.out.println(Thread.currentThread().getName() + " 对 " + account.toString() + " 取款了" + money + "元,余额是 " + account.getBalance());
}
}
//银行账户类
public class Account {
//账号
private String acton;
//余额
private double balance;
//构造方法
public Account() {
}
public Account(String acton, double balance) {
this.acton = acton;
this.balance = balance;
}
//set和get方法
public String getActon() {
return acton;
}
public void setActon(String acton) {
this.acton = acton;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
//取款方法
public void withdraw(double money){
//取前余额
double before = this.balance;
//取后余额
double after = before - money;
//模拟网络延迟,就一定会出错
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//更新余额
setBalance(after);
}
@Override
public String toString() {
return acton;
}
}
(二)synchronized第一种使用方式
public class Test {
public static void main(String[] args) {
//创建银行账户
Account account =new Account(“美国队长的账户”,10000);
//创建两个线程
//猎鹰和美国队长同时去取钱
AccountThread accountThread1 = new AccountThread(account);
AccountThread accountThread2 = new AccountThread(account);
accountThread1.setName(“美国队长”);
accountThread2.setName(“猎鹰”);
//取款
accountThread1.start();
accountThread2.start();
//猎鹰 对 美国队长的账户 取款了5000.0元,余额是 5000.0
//美国队长 对 美国队长的账户 取款了5000.0元,余额是 5000.0
//这就出错了
}
}
public class AccountThread extends Thread{
//同一个进程有相同的账号对象
//模拟两个人同时去ATM机器取钱
//has a
private Account account;
//构造方法,传入银行账户属性
public AccountThread(Account account) {
this.account = account;
}
@Override
//run方法的执行表示取款操作
public void run() {
//假设就取5000元钱
double money = 5000;
account.withdraw(money);
//取款信息
System.out.println(Thread.currentThread().getName() + " 对 " + account.toString() + " 取款了" + money + "元,余额是 " + account.getBalance());
}
}
(三)synchronized第二种使用方式
//银行账户类
public class Account {
//账号
private String acton;
//余额
private double balance;
//构造方法
public Account() {
}
public Account(String acton, double balance) {
this.acton = acton;
this.balance = balance;
}
//set和get方法
public String getActon() {
return acton;
}
public void setActon(String acton) {
this.acton = acton;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
//取款方法
public void withdraw(double money){
//以下的代码必须是排队的,要不然就可能会出问题
//一个线程把这里的代码全部执行完之后,另一个线程才能进来
/*
-
线程同步代码的语法
-
synchronized(){
}
-
synchronized 是一个关键字
-
后面的小括号填的东西非常重要,填的是你想要同步的线程的数据
-
这个数据必须是多线程的共享数据,才能达到多线程的排队
-
()里面写什么?
-
那看你想让哪些线程同步?
-
假设t1,t2,t3,t4,t5,有五个线程
-
你只希望t1,t2,t3排队,t4,t5不需要排队,怎么办?
-
你就在()中写一个t1,t3,t3共享的对象,而这个对象对于t4 t5来说是不共享的
-
*/
/*
-
对于这里来说,银行的账户是共享的,就可以填银行的账户
-
withdraw 是一个实例方法,所以this 就是银行对象
-
在java中,每一个对象都有一个对象锁
-
多少个对象,多少把锁
-
以下是线程同步的原理:
-
t1和t2两个线程:
-
1. 假设t1和t2线程是并发的,那么肯定一先一后执行下面的代码
-
假设t1先执行到这个代码,t1看到 synchronized 关键字就会去找后面的“后面共享对象”的对象锁,
-
找到之后就会占有这把锁,然后执行同步代码块的代码,在程序中一直占有这把锁,直到t1执行完毕,才会释放这个
-
“共享对象”的对象锁
-
2.假设t1已经占有了这把锁,t2这时候进到了synchronized中,去寻找对象锁,找到了对象锁,但是发现对象锁被t1占有了
-
那么也只能停下来,等到t1之星完毕,释放对象锁,才可以执行同步代码块
-
这样就达到了线程排队执行
-
这里要注意的是:这个共享对象一定要选好,
-
这个共享对象 是需要排队执行的这些线程对象所共享的
-
*/
//synchronized (object){ //也可以
//synchronized (“abc”){ //"abc"在字符串常量池当中,所有的线程都会等待
synchronized (this){
//取前余额
double before = this.balance;
//取后余额
double after = before - money;
//即使有网络延迟也没关系了
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//更新余额
setBalance(after);
}
}
@Override
public String toString() {
return acton;
}
}
package caopeng.javaseTest.threadsafetest.treadsafe3;
//银行账户类
public class Account {
//账号
private String acton;
//余额
private double balance;
//构造方法
public Account() {
}
public Account(String acton, double balance) {
this.acton = acton;
this.balance = balance;
}
//set和get方法
public String getActon() {
return acton;
}
public void setActon(String acton) {
this.acton = acton;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
//取款方法
//在方法的声明上使用synchronized,那么锁住一定是 this
//方法体就是同步代码块,可能会扩大同步的范围
//如果共享的就是this,并且需要同步的就是整个方法体,建议使用这个
//缺点:不够灵活
//优点:代码整洁
public synchronized void withdraw(double money){
//取前余额
double before = this.balance;
//取后余额
double after = before - money;
//模拟网络延迟,就一定会出错
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//更新余额
setBalance(after);
}
@Override
public String toString() {
return acton;
}
}
(四)synchronized第三种使用方式
在静态方法上用 synchronized 修饰,这个时候占用的是类锁,一个类一个锁,这个类的所有对象占有这一把锁
在下面的题目中最后一题有具体的代码实现
(一)题目一
//问 doOther需要等 dosome 结束吗
public class Exam {
public static void main(String[] args) {
//创建一个myClass对象
MyClass myClass =new MyClass();
//创建两个线程对象
Thread thread1 = new MyThread(myClass);
Thread thread2 = new MyThread(myClass);
thread1.setName(“钢铁侠”);
thread2.setName(“美国队长”);
//启动线程
thread1.start();
try {
Thread.sleep(1000);//确保 钢铁侠 线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
//dosome begin!!!
//doOther begin!!!
//doOther over!!!
//dosome over!!!
//不需要,因为doOther没有synchronized修饰,不需要对象锁,即使 myclass 对象的对象锁的确被 钢铁侠线程占有了
}
class MyThread extends Thread{
MyClass myClass;
public MyThread(MyClass myClass){
this.myClass = myClass;
}
public void run(){
if(Thread.currentThread().getName().equals(“钢铁侠”)){
myClass.dosome();
}else if (Thread.currentThread().getName().equals(“美国队长”)){
myClass.doOther();
}
}
}
class MyClass{
public synchronized void dosome(){
System.out.println(“dosome begin!!!”);
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“dosome over!!!”);
}
public void doOther(){
System.out.println(“doOther begin!!!”);
System.out.println(“doOther over!!!”);
}
}
(二)题目二
//问 doOther需要等 dosome 结束吗
public class Exam {
public static void main(String[] args) {
//创建一个myClass对象
MyClass myClass =new MyClass();
//创建两个线程对象
Thread thread1 = new MyThread(myClass);
Thread thread2 = new MyThread(myClass);
thread1.setName(“钢铁侠”);
thread2.setName(“美国队长”);
//启动线程
thread1.start();
try {
Thread.sleep(1000);//确保 钢铁侠 线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
//dosome begin!!!
//dosome over!!!
//doOther begin!!!
//doOther over!!!
//需要,因为 doOther此时也有Synchronized修饰,需要对象锁,但是doSome方法先执行,抢占了对象锁
//所以只能等 dosome方法执行完之后才能占有对象锁,然后执行同步代码块
}
class MyThread extends Thread{
MyClass myClass;
public MyThread(MyClass myClass){
this.myClass = myClass;
}
public void run(){
if(Thread.currentThread().getName().equals(“钢铁侠”)){
myClass.dosome();
}else if (Thread.currentThread().getName().equals(“美国队长”)){
myClass.doOther();
}
}
}
class MyClass{
public synchronized void dosome(){
System.out.println(“dosome begin!!!”);
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“dosome over!!!”);
}
public synchronized void doOther(){
System.out.println(“doOther begin!!!”);
System.out.println(“doOther over!!!”);
}
}
(三)题目三
//问 doOther需要等 dosome 结束吗
public class Exam {
public static void main(String[] args) {
//创建两个myClass对象
MyClass myClass1 =new MyClass();
MyClass myClass2 =new MyClass();
//创建两个线程对象
Thread thread1 = new MyThread(myClass1);
Thread thread2 = new MyThread(myClass2);
thread1.setName(“钢铁侠”);
thread2.setName(“美国队长”);
//启动线程
thread1.start();
try {
Thread.sleep(1000);//确保 钢铁侠 线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
//dosome begin!!!
//doOther begin!!!
//doOther over!!!
//dosome over!!!
//不需要,因为现在有两个对象,对象锁,一个对象一把锁,多少个对象,多少把锁
//现在有两个对象, 钢铁侠 线程占有的是myClass1的对象锁
//与myClass2 的对象锁 没有关系,所以不会影响到 doOther方法的执行
}
class MyThread extends Thread{
MyClass myClass;
public MyThread(MyClass myClass){
this.myClass = myClass;
}
public void run(){
if(Thread.currentThread().getName().equals(“钢铁侠”)){
myClass.dosome();
}else if (Thread.currentThread().getName().equals(“美国队长”)){
myClass.doOther();
}
}
}
class MyClass{
public synchronized void dosome(){
System.out.println(“dosome begin!!!”);
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“dosome over!!!”);
}
public synchronized void doOther(){
System.out.println(“doOther begin!!!”);
System.out.println(“doOther over!!!”);
}
}
(四)题目四
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
总结
总的来说,面试是有套路的,一面基础,二面架构,三面个人。
最后,小编这里收集整理了一些资料,其中包括面试题(含答案)、书籍、视频等。希望也能帮助想进大厂的朋友
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
ls(“钢铁侠”)){
myClass.dosome();
}else if (Thread.currentThread().getName().equals(“美国队长”)){
myClass.doOther();
}
}
}
class MyClass{
public synchronized void dosome(){
System.out.println(“dosome begin!!!”);
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“dosome over!!!”);
}
public synchronized void doOther(){
System.out.println(“doOther begin!!!”);
System.out.println(“doOther over!!!”);
}
}
(四)题目四
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-X0y7yUyH-1712205922394)]
[外链图片转存中…(img-S3a6ySkX-1712205922395)]
[外链图片转存中…(img-BaJpiUs8-1712205922395)]
[外链图片转存中…(img-0SmGneh4-1712205922396)]
[外链图片转存中…(img-aeSWZDNm-1712205922396)]
[外链图片转存中…(img-j1xrYG8L-1712205922396)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-DmlXC44Y-1712205922397)]
总结
总的来说,面试是有套路的,一面基础,二面架构,三面个人。
最后,小编这里收集整理了一些资料,其中包括面试题(含答案)、书籍、视频等。希望也能帮助想进大厂的朋友
[外链图片转存中…(img-gf0VzRug-1712205922397)]
[外链图片转存中…(img-DhYaf8hP-1712205922397)]
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算