java多线程--几个多线程面试题小结
自学了一段时间的多线程知识,尝试了做了几个编程题,发现想象中很简单的功能,自己真写起来要花费远超自己想象的功夫,知识点易学,不易用啊.
面试题1:编写程序实现,子线程循环10次,接着主线程循环20次,接着再子线程循环10次,主线程循环20次,如此反复,循环50次.
package com.wang.reflect;
//编写功能类,实现子线程和主线程的功能
class Function{
private boolean flag=false;
//子线程要实现的功能
public synchronized void sub(){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} for(int i=0;i<10;i++){
//for循环内定义子线程的功能,这里简单的假设为打印一句话,主线程同理
System.out.println("sub"+i);
} flag=true;
this.notify();
}
//主线程要实现的功能
public synchronized void main(){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<20;i++){
System.out.println("main"+i);
} flag=false;
this.notify();
} } public class Demo01 { public static void main(String[] args) {
final Function f=new Function();
new Thread(
new Runnable(){ @Override
public void run() {
for(int i=0;i<50;i++){
f.sub();
}
} }
).start(); for(int i=0;i<50;i++){
f.main();
}
}
}
JDK1.5以后,出现了Lock和condition,Lock类似于synchronized功能,用来进行线程同步,Condition功能类似于Object类中的wait和notify方法,用于线程间的通信.上面的代码可以用Lock和Condition来改进,如下:
package com.wang.reflect; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; //编写功能类,实现子线程和主线程的功能
class Function{
private boolean flag=false; Lock lock=new ReentrantLock();
Condition con=lock.newCondition();
//子线程要实现的功能
public void sub(){
lock.lock();
try { while(flag){
try {
con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} for(int i=;i<;i++){
//for循环内定义子线程的功能,这里简单的假设为打印一句话,主线程同理
System.out.println("sub"+i);
} flag=true;
con.signal();
} finally{
lock.unlock();
}
}
//主线程要实现的功能
public synchronized void main(){
lock.lock();
try {
while (!flag) {
try {
con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = ; i < ; i++) {
System.out.println("main" + i);
}
flag = false;
con.signal();
} finally{
lock.unlock();
}
} } public class Demo01 { public static void main(String[] args) {
final Function f=new Function();
new Thread(
new Runnable(){ @Override
public void run() {
for(int i=;i<;i++){
f.sub();
}
} }
).start(); for(int i=;i<;i++){
f.main();
}
}
}
面试题2:设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1.
package com.wang.reflect; /**
* 设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1.
* @author Administrator
*
*/
public class Demo02 { private int i=0;
public static void main(String[] args) {
Demo02 demo=new Demo02();
Add add = demo.new Add();
Sub sub = demo.new Sub();
for(int i=1;i<=2;i++){
new Thread(add,"线程"+i).start();
new Thread(sub,"线程"+i).start();
}
} //定义一个内部类Add,实现功能每次对i加一
class Add implements Runnable{ @Override
public void run() {
for(int i=0;i<10;i++){
addOne();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
//定义一个内部类Sub,实现功能每次对i减1
class Sub implements Runnable{ @Override
public void run() {
for(int i=0;i<10;i++){
subOne();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } public synchronized void addOne() {
i++;
System.out.println(Thread.currentThread().getName()+"加一的值为:"+i);
}
public synchronized void subOne(){
i--;
System.out.println(Thread.currentThread().getName()+"减一的值为:"+i);
}
}
面试题3:自己编写代码,实现生产者-消费者模型功能.内容自由发挥,只需要表达思想.
代码中,自定义一个学生类,有name和age属性,属于共享对象,生产者负责为studnet对象赋值,消费者负责打印出student对象的name和age的值,当生产者赋值完以后通知消费者来打印,消费者打印完以后,通知生产者重新设置.
package com.wang.reflect; //学生实体类作为共享资源
class Student {
private String name;// 姓名
private int age;// 年龄
boolean flag;// 标记变量,判断当前学生对象是否已创建赋值好 //生产者的功能 ,为studnet对象赋值
public synchronized void set(String name, int age) { if (this.flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
this.age = age; this.flag = true;
this.notify();
} //消费者的功能,打印sutdent对象的内容
public synchronized void get() {
if (!this.flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} System.out.println(name + ":::" + age); this.flag = false;
this.notify();
} } // 模拟生产者线程类
class SetStudent implements Runnable { // 共享资源s
private Student s;
private int x = 0; public SetStudent(Student s) {
this.s = s;
} @Override
public void run() {
while (true) {
if (x % 2 == 0) {
s.set("郭靖", 27);
} else {
s.set("黄蓉", 18);
}
x++;
}
} } // 模拟消费者线程类
class GetStudent implements Runnable { // 共享资源s
private Student s; public GetStudent(Student s) {
this.s = s;
} @Override
public void run() {
while (true) {
s.get();
}
} } // 测试类
public class Demo03{ public static void main(String[] args) {
Student s = new Student(); SetStudent ss = new SetStudent(s);
GetStudent gs = new GetStudent(s); Thread t1 = new Thread(ss, "生产者");
Thread t2 = new Thread(gs, "消费者"); t1.start();
t2.start();
} }
面试题4: 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。
原始代码如下:
public class Test {
public static void main(String[] args){
System.out.println("begin:"+(System.currentTimeMillis()/1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
*/
for(int i=0;i<16;i++){ //这行代码不能改动
final String log = ""+(i+1);//这行代码不能改动
{
Test.parseLog(log);
}
}
}
//parseLog方法内部的代码不能改动
public static void parseLog(String log){
System.out.println(log+":"+(System.currentTimeMillis()/1000));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
改写代码如下:
package com.wang.reflect; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; public class Demo03 { public static void main(String[] args){
//定义一个线程共享的队列容器,可以使得数据由队列的一端输入,从另外一端输出
final BlockingQueue<String> queue=new ArrayBlockingQueue<String>(16);
for(int i=0;i<4;i++){
new Thread(new Runnable(){ @Override
public void run() {
while(true){
try {
parseLog(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }).start();
} System.out.println("begin:"+(System.currentTimeMillis()/1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
*/
for(int i=0;i<16;i++){ //这行代码不能改动
final String log = ""+(i+1);//这行代码不能改动
{
try {
queue.put(log);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} //parseLog方法内部的代码不能改动
public static void parseLog(String log){
System.out.println(log+":"+(System.currentTimeMillis()/1000)); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
java多线程--几个多线程面试题小结的更多相关文章
- JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...
- JAVA多线程提高十四: 面试题
前面针对多线程相关知识点进行了学习,那么我们来来看看常见的面试题: 1. 空中网面试题1 package com.kongzhongwang.interview; import java.util.c ...
- 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)
在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...
- (原创)JAVA多线程一传统多线程
一,多线程 多线程是提高程序效率,避免资源浪费的很好的解决方案,下面来慢慢的介绍多线程的一些基本知识,而这些是晋级高级不可或缺的一部分 1,Thread类 类实现多线程需要实现Runnable接口,我 ...
- Java学习手记2——多线程
一.线程的概念 CPU执行程序,就好比一个人在干事情一样,同一个时间你只能做一件事情,但是这样的效率实在是太低了,在你用电脑的时候,听歌就不能浏览网页,看电影就不能下载视频,你想想是不是很蛋疼. 所以 ...
- java 并发性和多线程 -- 读感 (一 线程的基本概念部分)
1.目录略览 线程的基本概念:介绍线程的优点,代价,并发编程的模型.如何创建运行java 线程. 线程间通讯的机制:竞态条件与临界区,线程安全和共享资源与不可变性.java内存模型 ...
- Java 并发性和多线程
一.介绍 在过去单 CPU 时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程.虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个 ...
- Java 并发和多线程(一) Java并发性和多线程介绍[转]
作者:Jakob Jenkov 译者:Simon-SZ 校对:方腾飞 http://tutorials.jenkov.com/java-concurrency/index.html 在过去单CPU时 ...
- Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...
- Java并发性和多线程
Java并发性和多线程介绍 java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题, ...
随机推荐
- 安装OS X虚拟机错误vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1123
新建一个虚拟机, 选择客户机操作系统为Apple MacOS X 10.10, 其余参数可以默认. 注意建好之后不要急着打开客户机, 因为直接打开你会发现新建的客户机将会无法启动. 仔细阅读Mac O ...
- Ubuntu 14.04--php的安装和配置
更新源列表 打开"终端窗口",输入"sudo apt-get update"-->回车-->"输入root用户的密码"--& ...
- DES原理
1.DES的描述 为了建立适用于计算机系统的商用密码,美国商业部的国家标准局NBS于1973年5月和1974年8月两次发布通告,向社会征求密码算法.在征得的算法中,由IBM公司提出的算法lucifer ...
- DevOps是云计算时代的开发与运营
DevOps(英文Development和Operations的组合)是一组过程.方法与系统的统称,用于促进开发(应用程序/软件工程).技术运营和质量保障(QA)部门之间的沟通.协作与整合.[1] 它 ...
- Hadoop学习笔记—19.Flume框架学习
START:Flume是Cloudera提供的一个高可用的.高可靠的开源分布式海量日志收集系统,日志数据可以经过Flume流向需要存储终端目的地.这里的日志是一个统称,泛指文件.操作记录等许多数据. ...
- 【VC++技术杂谈007】使用GDI+进行图片格式转换
本文主要介绍如何使用GDI+对图片进行格式转换,可以转换的图片格式为bmp.jpg.png. 1.加载GDI+库 GDI+是GDI图形库的一个增强版本,提供了一系列Visual C++ API.为了使 ...
- Android开发学习之路-SnackBar使用心得
SnackBar是DesignSupportLibrary中的一个重要的控件,用于在界面下面提示一些关键信息,跟Toast不同的地方是SnackBar允许用户向右滑动消除它,同时,也允许在SnackB ...
- atom-shell程序打包
上一篇:http://www.cnblogs.com/luobenCode/p/4504910.html 打包之前要准备一下 请看这篇http://www.cnblogs.com/seanlv/arc ...
- MVC4做网站后台:用户管理 ——用户组补充
上次做完发现存在点问题. 1.是类型显示的为数字(如下图): 2.是不能根据类型进行查询. 首先做查询.easyui-datagrid可以添加toolbar. 在datagrid的data-optio ...
- Activity四种启动模式
转载博客:http://blog.csdn.net/shinay/article/details/7898492 Activity启动方式有四种,分别是:standardsingleTopsingle ...