您现在的位置是:主页 > news > 中山网站建点/如何发布自己的html网站
中山网站建点/如何发布自己的html网站
admin2025/5/1 5:25:02【news】
简介中山网站建点,如何发布自己的html网站,新城区网站建设,小企业网站服务器题是从网上搜的,便于整理,长期更新。 问题一:如何同时处理多条日志打印 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志…
题是从网上搜的,便于整理,长期更新。
问题一:如何同时处理多条日志打印
现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。原始代码如下:
交给四个线程,打印16个日志对象信息,启动四个线程容易,但是怎样将这16个日志对象交给4个线程,这时候我们用阻塞队列,将要打印的日志信息放到阻塞队列中,四个线程启动时都从阻塞队列中取数据,取完后打印即可。阻塞队列的大小可以自行设置。
修改为多线程打印日志信息后的代码及注释参考下文:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;/*** 多详情并行打印日志** @author Soinice* @date 2019/5/24 16:35*/
public class ThreadTestLog {/*** 模拟处理16行日志 每秒打印一条 开启4个线程 4秒打印完成** @param args* @return void* @author Soinice* @date 2019/5/24 17:32*/public static void main(String[] args) {System.out.println("begin:" + (System.currentTimeMillis() / 1000));final BlockingQueue<String> queue = new ArrayBlockingQueue<>(16);// 启动4个线程for (int i = 0; i < 4; i++) {new Thread(new Runnable() {@Overridepublic void run() {// 无限从堵塞队列中取出数据并打印while (true) {String log;try {log = queue.take();parseLog(log);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}// 循环16次,打印16个目标对象for (int i = 0; i < 16; i++) {final String log = "" + (i + 1);try {// 将日志信息放入阻塞队列queue.put(log);} catch (InterruptedException e) {e.printStackTrace();}}}/*** 解析日志 每一秒输出一条日志** @param log* @return void* @author Soinice* @date 2019/5/24 17:41*/private static void parseLog(String log) {System.out.println(log + ":" + (System.currentTimeMillis() / 1000));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}
}
问题二:如何用多线程实现简单的消费者生产者模式
现成程序中的Test类中的代码在不断地产生数据,然后交给BeforeRun.doSome()方法去处理,就好像生产者在不断地产生数据,消费者在不断消费数据。请将程序改造成有10个线程来消费生成者产生的数据,这些消费者都调用BeforeRun.doSome()方法去进行处理,故每个消费者都需要一秒才能处理完,程序应保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完后,下一个消费者才能消费数据,下一个消费者是谁都可以,但要保证这些消费者线程拿到的数据是有顺序的。原始代码如下:
/*** 多线程消费** @author Soinice* @date 2019/5/29 10:34*/
public class ThreadConsumerTest {public static void main(String[] args) {before();}/*** 处理之前** @param* @return void* @author Soinice* @date 2019/5/29 12:04*/private static void before() {System.out.println("begin:" + (System.currentTimeMillis() / 1000));for (int i = 0; i < 10; i++) {// 用于生产String input = i + "";// 调用消费方法String output = BeforeRun.doSome(input);System.out.println(Thread.currentThread().getName() + ":" + output);}}/*** 消费者在不断消费数据** @author Soinice* @date 2019/5/29 12:04*/static class BeforeRun {public static String doSome(String input) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}String output = input + ":" + (System.currentTimeMillis() / 1000);return output;}}
}
10个线程,依次消费数据,仍然是将待消费数据放入阻塞队列,让10个线程去取数据消费,所不同的是这次消费必须一个一个线程来,而不再是10个线程一起去取,因此用到了线程的同步。同步方法有多种,这里使用Semaphore来进行线程间的同步,代码及注释如下:
public static void main(String[] args) {
// before();after();}/*** 处理之后** @param* @return void* @author Soinice* @date 2019/5/29 14:06*/private static void after() {final SynchronousQueue<String> queue = new SynchronousQueue<String>();final Semaphore semaphore = new Semaphore(1);// 10个线程,分别消费数据,依旧是从阻塞队列中获取数据for (int i = 0; i < 10; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {semaphore.acquire();String input = queue.take();String output = Run.doSome(input);System.out.println(Thread.currentThread().getName() + ":" + output);semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}System.out.println("begin:" + (System.currentTimeMillis() / 1000));for (int i1 = 0; i1 < 10; i1++) {String input = i1 + "";try {queue.put(input);} catch (InterruptedException e) {e.printStackTrace();}}}
执行结果:
问题三:编写程序实现,子线程循环3次,接着主线程循环5次,接着再子线程循环3次,主线程循环5次,如此反复,循环3次。
第一种实现方式:使用synchronized关键字
/*** 第一种实现:使用Synchronized关键字** @param* @return void* @author lvyimeng* @date 2019/5/30 10:54*/private static void methodOne() {final ThreadMethodOne threadMethodOne = new ThreadMethodOne();// 调用子线程循环3次new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 3; i++) {threadMethodOne.subThread();}}}).start();// 调用主线程循环3次for (int i = 0; i < 3; i++) {threadMethodOne.mainThread();}}/*** 编写功能类,实现主子线程功能** @author lvyimeng* @date 2019/5/30 10:59*/static class ThreadMethodOne {private boolean flag = false;/*** 主线程** @param* @return void* @author lvyimeng* @date 2019/5/30 11:03*/public synchronized void mainThread() {while (!flag) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 主线程循环5次for (int i = 0; i < 5; i++) {System.out.println("mainThread" + i);}this.notify();flag = false;}/*** 子线程** @param* @return void* @author lvyimeng* @date 2019/5/30 14:42*/public synchronized void subThread() {while (flag) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 子线程循环3次for (int i = 0; i < 3; i++) {System.out.println("subThread" + i);}this.notify();flag = true;}}
执行结果:
第二种实现方式:使用 lock 锁和 Condition 接口
/*** 第二种实现:使用 lock 锁和 Condition 接口** @param* @return void* @author lvyimeng* @date 2019/5/30 17:39*/private static void methodTwo() {final ThreadMethodTwo threadMethodTwo = new ThreadMethodTwo();// 调用子线程循环3次new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 3; i++) {threadMethodTwo.subThread();}}}).start();// 调用主线程循环3次for (int i = 0; i < 3; i++) {threadMethodTwo.mainThread();}}/*** 编写功能类,实现子线程和主线程的功** @author lvyimeng* @date 2019/5/30 17:42*/static class ThreadMethodTwo extends Thread {private boolean flag = false;Lock lock = new ReentrantLock();Condition con = lock.newCondition();/*** 主线程** @param* @return void* @author lvyimeng* @date 2019/5/30 17:46*/public void mainThread() {System.out.println("1:主线程开始 ---- flag=" + flag);lock.lock();try {while (!flag) {System.out.println("2:主线程等待 ---- flag=" + flag);try {// 使当前线程加入 await() 等待队列中,// 并释放当前锁,当其他线程调用signal()会重新请求锁。与Object.wait()类似con.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("7.主线程开始循环5次 ---- flag=" + flag);for (int i = 0; i < 5; i++) {System.out.println("mainThread()" + i + " ---- flag=" + flag);}flag = false;System.out.println("8.唤醒子线程 ---- flag=" + flag);// 唤醒一个在 await() 等待队列中的线程,与Object.notify()相似con.signal();}} finally {lock.unlock();}}/*** 子线程** @param* @return void* @author lvyimeng* @date 2019/5/30 17:57*/public void subThread() {System.out.println("3.子线程开始 ---- flag=" + flag);lock.lock();try {while (flag) {System.out.println("6.子线程等待 ---- flag=" + flag);try {con.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("4.子线程开始循环3次 ---- flag=" + flag);for (int i = 0; i < 3; i++) {System.out.println("subThread()" + i + " ---- flag=" + flag);}flag = true;System.out.println("5.唤醒主线程 ---- flag=" + flag);con.signal();} finally {lock.unlock();}}}
执行结果:
Lock和synchronized的选择
总结来说,Lock和synchronized有以下几点不同:
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
问题四:设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1。
package cn.com.esgcc.gwtrip.hotel.service.biz;/*** 设计四个线程* 其中两个线程每次对变量i加1,另外两个线程每次对i减1** @author Soinice* @date 2019/5/30 18:17*/
public class ThreadCount {public static void main(String[] args) {final ThreadMethod threadMethod = new ThreadMethod();Thread thread = new Thread(new Runnable() {@Overridepublic void run() {threadMethod.add();}});Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {threadMethod.add();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {threadMethod.sub();}});Thread thread3 = new Thread(new Runnable() {@Overridepublic void run() {threadMethod.sub();}});thread.start();thread1.start();thread2.start();thread3.start();}static class ThreadMethod {private int i = 0;/*** 对变量 i加1*/public synchronized void add() {i++;System.out.println(Thread.currentThread().getName() + " ---- add():i = " + i);}/*** 对变量 i减1*/public synchronized void sub() {i--;System.out.println(Thread.currentThread().getName() + " ---- sub():i = " + i);}}
}