- 5、通过Thread类的对象调用start()*/
public class ThreadTest1 {
public static void main(String[] args) {
// 3、创建实现类的对象
MThread mThread = new MThread();
// 4、将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
Thread thread = new Thread(mThread);
// 5、通过Thread类的对象调用start()①启动线程②调用当前线程内的run()方法—>调用了Runnable类型的target的run()
thread.setName(“线程1:”);
thread.start();
// 再启动一个线程,遍历100以内的偶数
Thread thread1 = new Thread(mThread);
thread1.setName(“线程2:”);
thread1.start();
}
}
//1、创建实现了Runnable接口的类
class MThread implements Runnable{
//2、实现类去实现Runnable中的抽象方法:run()
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName()+ “:” + i);
}
}
}
}
开发中优先选择实现Runnable方式
原因:
-
实现的方式没有类的单继承性的局限性
-
实现的方式更适合来处理多个线程共享数据的情况
相同点:都需要重写run(),将线程要执行的代码声明在run()方法中
解决线程安全问题;
使用同步代码块
package com.haust.java;
/*出现线程安全问他的 解决方法:
- 当一个线程a在操作ticket的时候,其他线程不能参与进来,直到线程参与进来,也操作完ticket时,线程才可以开始操作ticket,这种情况即使线程a出现了阻塞,也不能被改变*/
/*在Java中,我们通过同步机制,来解决线程的安全问题
-
方式1:同步代码块
*synchronized(同步监视器){//需要被同步的代码}
-
说明:操作共享数据的代码,即为需要被同步的代码
-
共享数据:多个线程共同操作的变量,比如:ticket就是共享数据
-
同步监视器,俗称:锁。任何一个类的对象,都可以充当锁.
-
要求:多个线程必须要共用同一把锁。
-
方式2:同步方法
-
同步的方式解决了线程安全问题——好处
-
操作同步代码时,只能有一个线程参与,其他线程等待,相当于是一个单线程的过程,效率低
-
*/
public class WindowTest1 {
public static void main(String[] args) {
Window1 w = new Window1();
Thread thread1 = new Thread(w);
thread1.setName(“窗口1”);
Thread thread2= new Thread(w);
thread2.setName(“窗口2”);
thread1.start();
thread2.start();
}
}
class Window1 implements Runnable{
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while(true){
synchronized (obj){
if(ticket > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + “票号:” + ticket);
ticket–;
}
else
{
break;
}
}
}
}
}
使用同步方法
死锁
-
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
-
出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
解决方法
-
专门的算法、原则
-
进来减少同步资源的定义
-
进来避免嵌套同步
package com.haust.java1;
import java.util.concurrent.locks.ReentrantLock;
/*解决线程安全问题的方式三:Lock锁——JDK5.0新增
-
面试题:synchronized与Lock的异同点
-
相同点:二者都可以解决线程安全问题
-
不同点:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
-
Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())
-
面试题:如何解决线程安全问题 */
public class LockTest {
public static void main(String[] args) {
Window w = new Window();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName(“窗口1”);
t2.setName(“窗口2”);
t3.setName(“窗口3”);
t1.start();
t2.start();
t3.start();
}
}
class Window implements Runnable{
private int ticket = 100;
//1、实例化ReentrantLock
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while(true){
try {
//2、调用Lock方法
lock.lock();
if(ticket > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+“卖票:”+ticket);
ticket–;
}
else {
break;
}
}finally {
//3、调用解锁方法:unlock()
lock.unlock();
}
}
}
}
package com.haust.exer;
/*银行有一个账户
-
有两个储户分别想同一个账户存3000元,每次存1000,存3次,每次存完打印账户余额
-
分析:
-
1、是否是多线程问题?是,两个储户线程
-
2、是否有共享数据?有,账户(或账户余额)
-
3、是否有线程安全问题?有
-
4、是否需要考虑如何解决线程安全问题?同步机制:有三种方式
-
*/
class Account{
private double balance;
public Account(double balance) {
this.balance = balance;
}
//存储
public synchronized void deposit(double amt){
if (amt > 0){
balance += amt;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+“存钱成功,账户余额为:” + balance);
}
}
}
class Customer extends Thread{
private Account account;
public Customer(Account account){
this.account = account;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
account.deposit(1000);
}
}
}
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(“甲”);
c2.setName(“乙”);
c1.start();
c2.start();
}
}
package com.haust.java2;
/*线程通信的例子:使用两个线程打印1-100,线程A,线程B,交替打印
-
涉及到的三个方法:
-
wait()一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
-
notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级高的那个
-
notifyAll():一旦执行此方法,就会唤醒所有被wait的线程
-
说明:
-
1、wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中
-
2、wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现IllegalMonitorStateException异常*/
class Number implements Runnable{
private int number = 1;
@Override
public void run() {
while (true){
synchronized (this){
notify();
if(number <= 100){
System.out.println(Thread.currentThread().getName()+“:”+number);
number++;
try {
wait();//使得调用如下wait()方法的进程进入阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
{
break;
}
}
}
}
}
public class CommunicationTest {
public static void main(String[] args) {
Number number = new Number();
Thread t1 = new Thread(number);
Thread t2 = new Thread(number);
t1.setName(“A”);
t2.setName(“B”);
t1.start();
t2.start();
}
}
面试题:sleep()方法和wait()方法的异同
相同点:
- 一旦执行方法,都可以使得当前的线程进入阻塞状态
不同点:
-
两个方法声明的位置不同
-
Thread类中声明sleep(),Object类中声明wait()
-
调用的要求不同:
-
sleep()可以用在任何需要的场景下调用,wait()必须使用在同步代码块或同步方法中
-
关于是否释放同步监视器
-
如果两个方法都是用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁
package com.haust.java2;
/*线程通信的应用
-
分析:
-
1、是否有多线程问题?是,生产者线程,消费者线程
-
2、是否有共享数据?是店员
-
3、如何解决线程的安全问题?同步机制三种方法
-
4、是否涉及到线程的通信?是
-
*/
class Clerk{
private int productCount = 0;
//生产产品
public synchronized void produceProduct() {
if(productCount < 20){
productCount++;
System.out.println(Thread.currentThread().getName()+“开始生产第”+productCount+“个产品”);
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public synchronized void consumeProduct() {
if (productCount > 0){
System.out.println(Thread.currentThread().getName()+“开始销售第”+productCount+“个产品”);
productCount–;
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{
private Clerk clerk;
public Producer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName()+“:开始生产产品……”);
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProduct();
}
}
}
class Consumer extends Thread{
private Clerk clerk;
public Consumer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName()+“:开始购买产品……”);
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.consumeProduct();
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk c = new Clerk();
Producer p1 = new Producer©;
p1.setName(“生产者1”);
Consumer c1 = new Consumer©;
c1.setName(“消费者1”);
p1.start();
c1.start();
}
}
新增方式一:实现Callable接口
与使用Runnable相比,Callable功能更强大一下
-
相比run()方法,可以有返回值
-
方法可以抛出异常
-
支持范型的返回值
-
需要借助FutureTask类,比如获取返回结果
Future接口
-
可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等
-
FutureTask是Future接口的唯一实现类
-
FutureTask同时实现了Runnable,Future接口,它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
package com.haust.java2;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/*创建线程的方式三:实现Callable接口。JDK5.0新增
- */
//1、创建一个实现Callable的实现类
class NumThread implements Callable{
// 2、实现call()方法,将此线程需要执行的操作声明在call()中
@Override
public Object call() throws Exception {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后希望可以帮助到大家!
千千万万要记得:多刷题!!多刷题!!
之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!
篇幅有限,以下只能截图分享部分的资源!!
(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)
(2)刷的算法题(还有左神的算法笔记)
(3)面经+真题解析+对应的相关笔记(很全面)
(4)视频学习(部分)
ps:当你觉得学不进或者累了的时候,视频是个不错的选择
在这里,最后只一句话:祝大家offer拿到手软!!
学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-lVzDe23R-1711955140775)]
[外链图片转存中…(img-NyneoGRa-1711955140775)]
[外链图片转存中…(img-Trr8nIRD-1711955140776)]
[外链图片转存中…(img-LC8KhXq0-1711955140776)]
[外链图片转存中…(img-oZEKKvAV-1711955140776)]
[外链图片转存中…(img-PxsyK9Eq-1711955140776)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-PvM0IqPv-1711955140777)]
最后希望可以帮助到大家!
千千万万要记得:多刷题!!多刷题!!
之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!
篇幅有限,以下只能截图分享部分的资源!!
(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)
[外链图片转存中…(img-ol26XAaY-1711955140777)]
(2)刷的算法题(还有左神的算法笔记)
[外链图片转存中…(img-hU3iT1PY-1711955140777)]
(3)面经+真题解析+对应的相关笔记(很全面)
[外链图片转存中…(img-MqhUz2Ee-1711955140778)]
(4)视频学习(部分)
ps:当你觉得学不进或者累了的时候,视频是个不错的选择
在这里,最后只一句话:祝大家offer拿到手软!!