java 入门测试代码(六) 线程
今天弄了一下java 当中的线程
写了点代码
{
// 运行不返回的任务
class LiftOff implements Runnable {
protected int countDown = 10; // Default
public LiftOff() {
}
public LiftOff(int countDown) {
this.countDown = countDown;
}
public String status() {
// 得到当前的线程
Thread t = Thread.currentThread();
return "#" + t.getId() + "(" + (countDown > 0 ? countDown : "Liftoff!") + "), ";
}
public void run() {
while (countDown-- > 0) {
System.out.print(status());
Thread.yield();
}
}
}
// 创建线程池 这里可以是
// newFixedThreadPool
// newSingleThreadExecutor
// newCachedThreadPool 三种方式之一
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
{
// 可以返回的测试
class TaskWithResult implements Callable<String>
{
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
return "result of TaskWithResult " + id;
}
}
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList< Future<String> > results =
new ArrayList< Future<String> >();
for(int i = 0; i < 10; i++)
results.add( exec.submit(new TaskWithResult(i)) );
for(Future<String> fs : results)
try {
// get() blocks until completion:
System.out.println(fs.get());
} catch(InterruptedException e) {
System.out.println(e);
return;
} catch(ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
{
// 这里测试了内置锁和显式的锁两种方式的调用方法
// 如果这里不用锁出来的结果,就是乱序的,因为随时都可能运行进的切换行为
@ThreadSafe
class MyCounter implements Runnable{
private int c = 0;
private Lock m_c = new ReentrantLock();
public void increment() {
/*
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
c++;
}
public void decrement() {
c--;
}
public int getValue() {
return c;
}
@Override
public void run() {
/*
{
// 内置锁
synchronized (this) {
//incrementing
this.increment();
System.out.println("增加"
+ Thread.currentThread().getName() + " " + this.getValue());
//decrementing
this.decrement();
System.out.println("减少"
+ Thread.currentThread().getName() + " " + this.getValue());
}
}
*/
{
// 显式的锁
m_c.lock();
try {
//incrementing
this.increment();
System.out.println("增加"
+ Thread.currentThread().getName() + " " + this.getValue());
//decrementing
this.decrement();
System.out.println("减少"
+ Thread.currentThread().getName() + " " + this.getValue());
} finally {
m_c.unlock();
}
}
}
}
// 用线程池来创建
ExecutorService exec = Executors.newCachedThreadPool();
MyCounter counter = new MyCounter();
exec.execute( counter );
exec.execute( counter );
exec.execute( counter );
/*
// 用单个的线程来创建任务
MyCounter counter = new MyCounter();
Thread t1 = new Thread(counter, "Thread-1");
Thread t2 = new Thread(counter, "Thread-2");
Thread t3 = new Thread(counter, "Thread-3");
t1.start();
t2.start();
t3.start();
*/
}
// 生产消费者
{
new Restaurant();
}
// 线程日志
{
Logger logger = ThreadLogger.getLogger("main_log");
try {
ExecutorService executor = Executors.newCachedThreadPool();
logger.info("任务开始执行");
for (int i = 0; i < 3; i++) {
MyThread thread = new MyThread( String.valueOf(i) );
executor.submit( thread );
}
executor.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
logger.info("任务结束!");
}
// 死锁测试
{
class Client {
public static final String obj1 = "obj1";
public static final String obj2 = "obj2";
}
class DeadLockA extends Thread {
String _name;
DeadLockA( String name ){
this._name = name;
this.setName( name );
}
@Override
public void run() {
try {
System.out.println("LockA running" + this._name);
while (true) {
synchronized (Client.obj1) {
System.out.println("LockA locked obj1");
//获取obj1后先等一会儿,让LockB有足够的时间锁住obj2
Thread.sleep(100);
System.out.println("LockA trying to lock obj2...");
synchronized (Client.obj2) {
System.out.println("LockA locked obj2");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class DeadLockB extends Thread {
String _name;
DeadLockB( String name ){
this._name = name;
this.setName( name );
}
@Override
public void run() {
try {
System.out.println("LockB running" + this._name );
while (true) {
synchronized (Client.obj2) {
System.out.println("LockB locked obj2");
System.out.println("LockB trying to lock obj1...");
synchronized (Client.obj1) {
System.out.println("LockB locked obj1");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
new DeadLockA("A__").start();
new DeadLockB("B__").start();
}
// CyclicBarrier 测试
{
//最后执行的任务
class MainTask implements Runnable
{
public void run() {
System.out.println("......终于要执行最后的任务了......");
}
}
// 一组并发任务
class SubTask extends Thread {
private String name;
private CyclicBarrier barrier;
SubTask(String name, CyclicBarrier barrier) {
this.name = name;
this.barrier = barrier;
}
public void run()
{
System.out.println("[并发任务" + name + "] 开始执行");
for (int i = 0; i < 999999; i++) ; //模拟耗时的任务
System.out.println("[并发任务" + name + "] 开始执行完毕,通知障碍器");
try {
//每执行完一项任务就通知障碍器
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
CyclicBarrier cb = new CyclicBarrier(5, new MainTask());
new SubTask("A", cb).start();
new SubTask("B", cb).start();
new SubTask("C", cb).start();
new SubTask("D", cb).start();
new SubTask("E", cb).start();
}
// DelayQueue 使用
{
/**
* 延时消息实体
* @author slimina
*
*/
class Message implements Delayed{
private int id;
private String body; //消息内容
private long excuteTime;//执行时间
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public long getExcuteTime() {
return excuteTime;
}
public void setExcuteTime(long excuteTime) {
this.excuteTime = excuteTime;
}
public Message(int id, String body,long delayTime) {
this.id = id;
this.body = body;
this.excuteTime = TimeUnit.NANOSECONDS.convert(delayTime, TimeUnit.MILLISECONDS) + System.nanoTime();
}
@Override
public int compareTo(Delayed delayed) {
Message msg = (Message)delayed;
return Integer.valueOf(this.id)>Integer.valueOf(msg.id)?1:( Integer.valueOf(this.id)<Integer.valueOf(msg.id)?-1:0);
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.excuteTime - System.nanoTime(), TimeUnit.NANOSECONDS);
}
}
//消息的消費者
class MessageUser implements Runnable {
// 延时队列
private DelayQueue<Message> queue;
public MessageUser(DelayQueue<Message> queue) {
this.queue = queue;
}
@Override
public void run()
{
while (true)
{
try {
Message take = queue.take();
System.out.println("消费消息:" + take.getId() + ":" + take.getBody());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 创建延时队列
DelayQueue<Message> queue = new DelayQueue<Message>();
Message m1 = new Message(1, "第一条消息的通知。。。。", 3000);
Message m2 = new Message(2, "第二条消息的通知。。。", 5000);
Message m3 = new Message(3, "第3条消息的通知。。。", 7000);
Message m4 = new Message(4, "第4条消息的通知。。。", 8000);
queue.add(m1);
queue.add(m2);
queue.add(m3);
queue.add(m4);
//queue.offer(m1);
//queue.offer(m2);
//queue.offer(m3);
//queue.offer(m4);
// 启动消费线程
new Thread(new MessageUser(queue)).start();
}
生产消费者类如下所示:
package com.company;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Meal {
private final int orderNum;
public Meal(int orderNum) {
this.orderNum = orderNum;
}
public String toString() {
return "Meal " + orderNum;
}
}
class WaitPerson implements Runnable {
private Restaurant restaurant;
public WaitPerson(Restaurant r) {
restaurant = r;
}
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (restaurant.meal == null)
wait(); // ... for the chef to produce a meal
}
System.out.println("Waitperson got " + restaurant.meal);
synchronized (restaurant.chef) {
restaurant.meal = null;
restaurant.chef.notifyAll(); // Ready for another
}
}
} catch (InterruptedException e) {
System.out.println("WaitPerson interrupted");
}
}
}
class Chef implements Runnable {
private Restaurant restaurant;
private int count = 0;
public Chef(Restaurant r) {
restaurant = r;
}
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (restaurant.meal != null)
wait(); // ... for the meal to be taken
}
if (++count == 10) {
System.out.println("Out of food, closing");
restaurant.exec.shutdownNow();
}
System.out.println("Order up! ");
synchronized (restaurant.waitPerson) {
restaurant.meal = new Meal(count);
restaurant.waitPerson.notifyAll();
}
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Chef interrupted");
}
}
}
public class Restaurant {
Meal meal;
ExecutorService exec = Executors.newCachedThreadPool();
WaitPerson waitPerson = new WaitPerson(this);
Chef chef = new Chef(this);
public Restaurant() {
exec.execute(chef);
exec.execute(waitPerson);
}
}
线程日志的生成:
1. 用库
log4j-1.2.16.jar
2. 引入工程
3. Mythread.java
package com.company;
import org.apache.log4j.Logger;
public class MyThread implements Runnable {
String logName;
public MyThread(String logName) {
this.logName = logName;
}
public void run() {
// 在run方法内实现线程独立的logger实例
Logger logger = ThreadLogger.getLogger(logName);
logger.info(logName + "_" + Thread.currentThread().getName() + " started!");
logger.error("this is error!");
logger.info(logName + "_" + Thread.currentThread().getName() + " finished!");
}
}
4. ThreadLogger.java
package com.company;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class ThreadLogger {
public static Logger getLogger(String logName) {
Logger logger = null;
logger = Logger.getLogger(logName);
PatternLayout layout = new PatternLayout("[%d{MM-dd HH:mm:ss}] %-5p %-8t %m%n");
// 日志文件按照每天分文件夹存放
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String logPath = "D://logs/log4jTest/" + sdf.format(new Date()) + "/";
// 文件输出
ThreadLogger.ThreadFileAppender fileAppender = null;
try {
fileAppender = new ThreadFileAppender(layout, logPath, logName, "yyyy-MM-dd");
} catch (IOException e) {
e.printStackTrace();
}
fileAppender.setAppend(false);
fileAppender.setImmediateFlush(true);
fileAppender.setThreshold(Level.DEBUG);
// 绑定到logger
logger.setLevel(Level.DEBUG);
logger.addAppender(fileAppender);
return logger;
}
/*
* 继承了log4j类的内部类
*/
public static class ThreadFileAppender extends DailyRollingFileAppender {
public ThreadFileAppender(Layout layout, String filePath, String fileName, String datePattern)
throws IOException {
super(layout, filePath + fileName + ".log", datePattern);
}
}
}
5. 调用:
// 线程日志
{
Logger logger = ThreadLogger.getLogger("main_log");
try {
ExecutorService executor = Executors.newCachedThreadPool();
logger.info("任务开始执行");
for (int i = 0; i < 3; i++) {
MyThread thread = new MyThread( String.valueOf(i) );
executor.submit( thread );
}
executor.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
logger.info("任务结束!");
}
关于死锁测试及idea当中的调试的问题:
1. 运行上边的程序
2. 在idea当中查看:
小眼睛可以看到当前的 get thread dump 当中的信息,也可以用jstack工具来看线程的状态信息,都可以看到对应的线程现在发生了 dead lock.