1,模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完整这些日志修改程序代码,开四个线程让这16个对象在4秒内打印完成
源代码:
public class LogTest {
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 = String.valueOf(i+1);//这行代码也不能改动
{
LogTest.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();
}
}
/**
* 运行结果:
begin:1350916219
1:1350916219
2:1350916220
3:1350916221
4:1350916222
5:1350916223
6:1350916224
7:1350916225
8:1350916226
9:1350916227
10:1350916228
11:1350916229
12:1350916230
13:1350916231
14:1350916232
15:1350916233
16:1350916234
*/
}
答案:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class LogTest {
public static void main(String[] args) {
final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);
System.out.println("begin:"+(System.currentTimeMillis()/1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完整这些日志
修改程序代码,开四个线程让这16个对象在4秒内打印完成*/
for(int i=0; i<16; i++){//这行代码不能改动
final String log = String.valueOf(i+1);//这行代码也不能改动
{
try {
queue.put(log);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(queue.size());
for(int i=0; i<4; i++){
System.out.println("####");
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
String log = queue.take();
parseLog(log);
} catch (Exception e) {
}
}
}}).start();
}
}
//parseLog方法内部的代码也不能改动
public static void parseLog(String log){
System.out.println(log+":"+(System.currentTimeMillis()/1000));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 运行结果:
begin:1350917923
16
####
####
####
1:1350917923
####
2:1350917923
3:1350917923
4:1350917923
5:1350917924
6:1350917924
8:1350917924
7:1350917924
9:1350917925
11:1350917925
10:1350917925
12:1350917925
13:1350917926
15:1350917926
14:1350917926
16:1350917926
*/
}
2、主线程循环5次,子线程循环10次,依次循环50次
public class MainSub {
/**
* 要用到共同数据(包括同步锁)或共同算法的若干个方法应该归在同一个类身上,
* 这种设计体现了高内聚和程序的健壮性
*/
private static Business busi = new Business();
public static void main(String[] args) {
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0; i<50; i++){
busi.sun(i);
}
}
}).start();
for(int i=0; i<50; i++){
busi.main(i);
}
}
}
class Business{
boolean Ismain = true;
public synchronized void main(int i){
while(!Ismain){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0; j<5; j++){
System.out.println("main:第"+i+"个循环的下标为"+j);
}
System.out.println("-----------------------------------");
Ismain = false;
notifyAll();
}
public synchronized void sun(int i){
while(Ismain){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0; j<10; j++){
System.out.println("sub:第"+i+"个循环的下标为"+j);
}
System.out.println("-----------------------------------");
Ismain = true;
notifyAll();
}
/**
* 运行结果:
* main:第0个循环的下标为0
main:第0个循环的下标为1
main:第0个循环的下标为2
main:第0个循环的下标为3
main:第0个循环的下标为4
-----------------------------------
sub:第0个循环的下标为0
sub:第0个循环的下标为1
sub:第0个循环的下标为2
sub:第0个循环的下标为3
sub:第0个循环的下标为4
sub:第0个循环的下标为5
sub:第0个循环的下标为6
sub:第0个循环的下标为7
sub:第0个循环的下标为8
sub:第0个循环的下标为9
-----------------------------------
main:第1个循环的下标为0
main:第1个循环的下标为1
main:第1个循环的下标为2
main:第1个循环的下标为3
main:第1个循环的下标为4
-----------------------------------
sub:第1个循环的下标为0
sub:第1个循环的下标为1
sub:第1个循环的下标为2
sub:第1个循环的下标为3
sub:第1个循环的下标为4
sub:第1个循环的下标为5
sub:第1个循环的下标为6
sub:第1个循环的下标为7
sub:第1个循环的下标为8
sub:第1个循环的下标为9
*/
}
3、设计四个线程,其中两个线程每次对i进行增加1,另外两个线程每次对i进行减少1,循环100次
public class Test12 {
public static void main(String[] args) {
Test12 t = new Test12();
Inc inc = t.new Inc();//需要是同一个对象,用同一个锁
Dec dec = t.new Dec();
for(int i=0; i<2; i++){
Thread t1 = new Thread(inc);
t1.start();
Thread t2 = new Thread(dec);
t2.start();
}
}
int i = 0;
public synchronized void add(){
i ++ ;
System.out.println("++操作,当前i值为:"+i);
}
public synchronized void lost(){
i -- ;
System.out.println("--操作,当前i值为:"+i);
}
class Inc implements Runnable{
@Override
public void run() {
// for(int i=0; i<100; i++)
add();
}
}
class Dec implements Runnable{
@Override
public void run() {
// for(int i=0; i<100; i++)
lost();
}
}
/**
++操作,当前i值为:1
--操作,当前i值为:0
++操作,当前i值为:1
--操作,当前i值为:0
*/
}
4,当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
分几种情况:
1.其他方法前是否加了synchronized关键字,如果没加,则能。
2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。
3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。
4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。