首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
搜索
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
在线笔面试、雇主品牌宣传
登录
/
注册
叙利亚俏悍妇
四川大学 Java
发布于江苏
关注
已关注
取消关注
java 手写题
@Java抽象带篮子:
java手写题汇总(建议收藏)
1.创建线程 共有四种方式可以创建线程,分别是:继承Thread类、实现runnable接口、实现Callable接口、线程池创建线程 详细创建方式参考下面代码: ① 继承Thread类 public class MyThread extends Thread { @Override public void run() { System.out.println("MyThread...run..."); } public static void main(String[] args) { // 创建MyThread对象 MyThread t1 = new MyThread() ; MyThread t2 = new MyThread() ; // 调用start方法启动线程 t1.start(); t2.start(); } } ② 实现runnable接口 public class MyRunnable implements Runnable{ @Override public void run() { System.out.println("MyRunnable...run..."); } public static void main(String[] args) { // 创建MyRunnable对象 MyRunnable mr = new MyRunnable() ; // 创建Thread对象 Thread t1 = new Thread(mr) ; Thread t2 = new Thread(mr) ; // 调用start方法启动线程 t1.start(); t2.start(); }} ③ 实现Callable接口 public class MyCallable implements Callable<String> {//MyCallable类实现了Callable<String>接口,该接口是一个泛型接口,指定了call()方法的返回类型为String @Override public String call() throws Exception {//call方法可以抛出异常 System.out.println("MyCallable...call..."); return "OK"; } public static void main(String[] args) throws ExecutionException, InterruptedException { // 创建MyCallable对象 MyCallable mc = new MyCallable() ; //创建FutureTask<String>对象ft,并将mc作为参数传入构造方法,用于封装可调用对象 FutureTask<String> ft = new FutureTask<String>(mc) ; //通过将Callable对象封装在FutureTask中,可以在多线程环境下执行任务,并获取任务执行结果。 // 创建Thread对象 Thread t1 = new Thread(ft) ; Thread t2 = new Thread(ft) ; // 调用start方法启动线程 t1.start(); //调用ft.get()方法获取执行结果,此方法会阻塞当前线程直到结果返回。 String result = ft.get(); // 输出 System.out.println(result); }}//输出结果MyCallable...call...OK ④ 线程池创建线程 public class MyExecutors implements Runnable{ @Override public void run() { System.out.println("MyRunnable...run..."); } public static void main(String[] args) { // 创建线程池对象。获取ExecutorService实例,生产禁用,需要手动创建线程池 ExecutorService threadPool = Executors.newFixedThreadPool(3); //通过threadPool.submit(new MyExecutors())来向线程池提交任务。 threadPool.submit(new MyExecutors()) ; //调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭,但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。 threadPool.shutdown(); }} 2.手写线程池 public class ThreadPoolExecutorTest {//它创建了一个线程池,最大线程数为5,核心线程数为2,空闲线程存活时间为2秒,任务队列容量为3。然后向线程池提交了5个任务,每个任务打印当前线程的名称和"ok"。最后关闭线程池。//跑6条线程,那么6 >= 核心线程数+阻塞队列中的线程数,就会启用其他三条线程中的一个//跑8条线程,那么8 >= 核心线程数+阻塞队列中的线程数,就会启用其他三条线程中的三个//跑9条线程,那么9 >= 核心线程数+阻塞队列中的线程数,且9 > 最大线程数(5) + 阻塞队列中的线程数(8),则会触发拒绝策略,这里使用的拒绝策略是AbortPolicy,也就是拒绝处理,并抛出异常 public static void main(String[] args) { ExecutorService threadPool = new ThreadPoolExecutor( 2, 5, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() //当线程池无法接受新任务时,会触发拒绝策略,内置的拒绝策略有四种: AbortPolicy:默认策略,直接抛出 RejectedExecutionException 异常。 CallerRunsPolicy:由调用者线程执行任务。 DiscardPolicy:默默地丢弃任务,没有任何异常抛出。 DiscardOldestPolicy:尝试抛弃队列中最旧的任务,然后重新尝试提交当前任务。 ); try { for (int i = 1; i <= 5 ; i++) { threadPool.execute(()-> { System.out.println(Thread.currentThread().getName() + "ok"); }); } } catch (Exception e) { e.printStackTrace(); } finally { threadPool.shutdown(); } }}/** * pool-1-thread-1ok * pool-1-thread-2ok * pool-1-thread-2ok * pool-1-thread-2ok * pool-1-thread-1ok */ 3. 新建 T1、T2、T3 三个线程,如何保证它们按顺序执行? 可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。 代码举例: 为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成 public class JoinTest { public static void main(String[] args) { // 创建线程对象 Thread t1 = new Thread(() -> { System.out.println("t1"); }) ; Thread t2 = new Thread(() -> { try { t1.join(); // 加入线程t1,只有t1线程执行完毕以后,再次执行该线程 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t2"); }) ; Thread t3 = new Thread(() -> { try { t2.join(); // 加入线程t2,只有t2线程执行完毕以后,再次执行该线程 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t3"); }) ; // 启动线程 t1.start(); t2.start(); t3.start(); }} 4.synchronized解决抢票超卖问题 如下抢票的代码,如果不加锁,就会出现超卖或者一张票卖给多个人 Synchronized【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其它线程再想获取这个【对象锁】时就会阻塞住 public class TicketDemo { static Object lock = new Object(); int ticketNum = 10; public synchronized void getTicket() { synchronized (this) { if (ticketNum <= 0) { return; } System.out.println(Thread.currentThread().getName() + "抢到一张票,剩余:" + ticketNum); // 非原子性操作 ticketNum--; } } public static void main(String[] args) { TicketDemo ticketDemo = new TicketDemo(); for (int i = 0; i < 20; i++) { new Thread(() -> { ticketDemo.getTicket(); }).start(); } }} 5.线程死锁代码 死锁:线程死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去。 package com.itheima.basic;import static java.lang.Thread.sleep;public class Deadlock { //t1 线程获得A资源,接下来想获取B资源 //t2 线程获得B资源,接下来想获取A资源 public static void main(String[] args) { Object A = new Object(); Object B = new Object(); Thread t1 = new Thread(() -> { synchronized (A) { System.out.println(Thread.currentThread() + "get resource1"); try { sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } synchronized (B) { System.out.println(Thread.currentThread() + "get resource1"); } } }, "t1"); Thread t2 = new Thread(() -> { synchronized (B) { System.out.println(Thread.currentThread() + "get resource1"); try { sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } synchronized (A) { System.out.println(Thread.currentThread() + "get resource1"); } } }, "t2"); t1.start(); t2.start(); }} 6.Semaphore信号量 synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,而Semaphore(信号量)可以用来控制同时访问特定资源的线程数量。 以下代码模拟了对某个服务的并发请求,每次只能有 3 个客户端同时访问,请求总数为 10。 public class SemaphoreExample { public static void main(String[] args) { final int clientCount = 3; final int totalRequestCount = 10; //意味着最多允许clientCount个线程同时执行 Semaphore semaphore = new Semaphore(clientCount); ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < totalRequestCount; i++) { executorService.execute(()->{ try { //调用semaphore.acquire()方法获取信号量。如果当前信号量的可用资源数量大于0,则会直接获取资源并继续执行;否则,线程将被阻塞,直到有可用资源为止。 semaphore.acquire(); //在获取资源后,打印出当前信号量的可用资源数量,即semaphore.availablePermits()。 System.out.print(semaphore.availablePermits() + " "); } catch (InterruptedException e) { e.printStackTrace(); } finally { //release()方法释放了一个信号量 semaphore.release(); } }); } //调用executorService.shutdown()方法关闭线程池 executorService.shutdown(); } 7. CyclicBarrier(同步屏障) yclicBarrier(同步屏障),用于一组线程互相等待到某个状态,然后这组线程再同时执行。 通过CyclicBarrier实现了一种线程同步机制,即在所有线程都到达某个点之前,它们会一直等待;当所有线程都到达该点后,才会继续执行后续代码。 public class CyclicBarrierExample { public static void main(String[] args) { final int totalThread = 10;//表示线程总数 CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread); ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < totalThread; i++) { executorService.execute(() -> { System.out.print("before.."); try { //调用cyclicBarrier.await()进行等待,直到所有线程都到达屏障点。 cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } System.out.print("after.."); }); } //调用executorService.shutdown()关闭线程池。 executorService.shutdown(); }}//输出结果before..before..before..before..before..before..before..before..before..before..after..after..after..after..after..after..after..after..after..after.. 7.CountDownLatch倒计时锁 CountDownLatch倒计时锁用于某个线程等待其他线程执行完任务再执行,与thread.join()功能类似。常见的应用场景是开启多个线程同时执行某个任务,等到所有任务执行完再执行特定操作,如汇总统计结果 其中构造参数用来初始化等待计数值 await() 用来等待计数归零,调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行;等待timeout时间后count值还没变为0的话就会继续执行 countDown() 用来让计数减一 在这个例子中,我们创建了一个CountDownLatch实例,其计数器初始值为3。然后创建了3个线程,每个线程执行一个Worker任务。Worker任务完成后,调用latch.countDown()将计数器减一。主线程通过调用latch.await()等待所有子线程完成任务(即计数器变为0)。当所有子线程完成任务后,主线程继续执行并输出"所有子线程任务已完成"。 import java.util.concurrent.CountDownLatch;public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { int numberOfThreads = 3; CountDownLatch latch = new CountDownLatch(numberOfThreads); for (int i = 0; i < numberOfThreads; i++) { new Thread(new Worker(latch)).start(); } // 主线程等待所有子线程完成任务 latch.await(); System.out.println("所有子线程任务已完成"); } static class Worker implements Runnable { private final CountDownLatch latch; public Worker(CountDownLatch latch) { this.latch = latch; } @Override public void run() { try { // 模拟耗时任务 Thread.sleep((long) (Math.random() * 1000)); System.out.println(Thread.currentThread().getName() + " 完成任务"); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 完成任务后,计数器减一 latch.countDown(); } } }}Thread-2 完成任务Thread-1 完成任务Thread-0 完成任务所有子线程任务已完成 8.重写equals()的例子 在这个示例中,我们创建了一个Person类,包含name和age两个属性。我们重写了hashCode()方法,首先定义一个初始值为17的变量result,然后分别将name和age的哈希值乘以31并加到result上,最后返回result作为对象的哈希码值。这样做的目的是为了让不同的对象尽可能地产生不同的哈希码值,从而提高哈希表等数据结构的性能。 public class Person { private String name; private int age; // 构造函数和其他方法... @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } Person person = (Person) obj; return age == person.age && name.equals(person.name); } @Override public int hashCode() { int result = 17; // 初始值 result = 31 * result + name.hashCode(); // 使用字符串的hashCode()方法计算哈希值 result = 31 * result + age; // 直接将年龄加入哈希值计算 return result; }} 9.约瑟夫环问题 约瑟夫环问题的故事背景源自于历史学家约瑟夫斯·弗拉维奥·约瑟夫的《犹太战争》中描述的一个历史事件。在这个问题中,一群人围成一圈,从某个人开始报数,每报到一个特定的数字,那个人就会离开圈子,然后从下一个人开始重新报数,直到最后只剩下一个人。这个问题的目的是找出最后留下的那个人最初的位置。 #include <iostream>using namespace std;// 定义链表节点结构体struct Node { int data; // 节点数据 Node* next; // 指向下一个节点的指针};// 创建循环链表Node* createList(int n) { Node* head = new Node(); // 创建头节点 head->data = 1; head->next = NULL; Node* temp = head; // 临时指针,用于连接节点 for (int i = 2; i <= n; i++) { Node* newNode = new Node(); // 创建新节点 newNode->data = i; newNode->next = NULL;
点赞 158
评论 18
全部评论
推荐
最新
楼层
Java抽象带篮子
中南大学 Java
{"pureText":"😋","imgs":[]}
点赞
回复
分享
发布于 08-14 00:48
北京
还没有回复哦~
相关推荐
11-21 15:06
已编辑
中国矿业大学(北京) 后端
【简历】25届一本JAVA简历:秒杀真不能做到校招主项目了
注:为保证用户信息安全,姓名和学校等信息已经进行同层次变更,内容部分细节也进行了部分隐藏另外:我们出这一系列校招简历指导的原因,就是看很多学生被忽悠,没有先定位大厂、中厂还是小公司,导致没有面试机会。 我们不放任何的广告和品牌名,完全是反馈牛客社区。大家也不要私信,现在比较忙,没空帮大家改简历。简历总体说明 校招的第一法则就是必须要确定校招层次。 开发岗分为大中小厂,不同的层次对学校背景、时间点、项目和考点的要求都不太一样,所以必须要确定就业的层次。 这是一份苏州某一本大学的JAVA简历。之前,我们一直强调校招首先要确定层次,一本的25届学生校招的主体就是中厂。并且现在秋招...
投递牛客等公司10个岗位 >
你的秋招简历被谁挂了?
你的简历改到第几版了
点赞
评论
收藏
分享
今天 13:37
已编辑
贵阳人文科技学院 Web前端
简历建议,大佬们能帮忙提提建议吗
感觉白学了,浪费了半年来考研,现在考研也无望了,秋招也没有跟上,怎么办呀我还能有机会入行吗。
简历中的项目经历要怎么写
秋招被确诊为……
点赞
评论
收藏
分享
11-06 13:27
哈尔滨工业大学(威海) C++
上岸啦 秋招第一个offer
太开心了 结束秋招!祝大家好运哦
机灵的灰太狼顶呱呱:
又枫一个
点赞
评论
收藏
分享
不愿透露姓名的神秘牛友
11-21 19:05
帮看
点赞
评论
收藏
分享
点赞成功,聊一聊 >
点赞
收藏
评论
分享
回复帖子
提到的真题
返回内容
全站热榜
1
...
从露宿街头到百万级种子轮融资——我的大学时代经历了什么
3.4W
2
...
C++选手秋招总结
1.4W
3
...
字节20多面终究一场空
1.3W
4
...
不装了!牛客就是OFFER判官
1.1W
5
...
华为电话oc了
9672
6
...
泡出来啦
9163
7
...
秋招圆满结束
8004
8
...
阿里云管培生开奖了
6162
9
...
结束了,一切都结束了。。
5772
10
...
爱信等
5398
正在热议
#
25届秋招总结
#
328639次浏览
3103人参与
#
上班苦还是上学苦呢?
#
72673次浏览
652人参与
#
阿里云管培生offer
#
37048次浏览
422人参与
#
地方国企笔面经互助
#
4507次浏览
12人参与
#
如果有时光机,你最想去到哪个年纪?
#
21749次浏览
402人参与
#
选完offer后,你后悔学本专业吗
#
21908次浏览
159人参与
#
百度开奖
#
184001次浏览
1152人参与
#
我的实习求职记录
#
6070608次浏览
83542人参与
#
如何一边实习一边秋招
#
996748次浏览
12664人参与
#
找工作时遇到的神仙HR
#
553440次浏览
3801人参与
#
入职第一天,你准备什么时候下班
#
21639次浏览
144人参与
#
招聘要求与实际实习内容不符怎么办
#
10784次浏览
277人参与
#
bilibili求职进展汇总
#
33233次浏览
357人参与
#
许愿池
#
214793次浏览
2534人参与
#
学历or实习经历,哪个更重要
#
53913次浏览
423人参与
#
你今年的平均薪资是多少?
#
70863次浏览
345人参与
#
实习工作,你找得还顺利吗?
#
247760次浏览
2907人参与
#
通信硬件薪资爆料
#
609025次浏览
5193人参与
#
海康威视求职进展汇总
#
400768次浏览
3408人参与
#
携程求职进展汇总
#
135798次浏览
931人参与
#
正在实习的你,几点下班
#
53369次浏览
396人参与
#
工作两年想退休了
#
53113次浏览
672人参与
牛客网
牛客企业服务