java多线程学习(二)
标签(空格分隔): java 线程
线程的优先级别
java提供一个线程调度器来监控程序中启动后所有进入就绪状态的线程,线程调度器按照线程优先级执行线程。
线程优先级从1到10,用数字表示,从低到高,缺省的默认值为5使用下面方法设置或者获取线程的优先级:
- int getPriority()
- void setPriority(int num)
java 线程使用
/**
*
*/
package com.frankstar.Thread;
/**
* @author frankstar
* 线程优先级测试
*/
public class PriorityThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TestPriorityThread1 tpt1 = new TestPriorityThread1();
TestPriorityThread2 tpt2 = new TestPriorityThread2();
Thread t1 = new Thread(tpt1);
Thread t2 = new Thread(tpt2);
// t1.start();
// t2.start(); //先看未设置优先级的进程
// 这里的优先级指的是执行一次的时间会较长即占据CPU时间片的时间会比较多
t1.setPriority(Thread.NORM_PRIORITY + 3);
t1.start();
t2.start();
System.out.println("t1的优先级为: " + t1.getPriority());
}
}
class TestPriorityThread1 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <= 5; i++) {
System.out.println("1st: " + i);
}
}
}
class TestPriorityThread2 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <= 5; i++) {
System.out.println("2st: " + i);
}
}
}
线程的同步
- java中,引入了互斥锁的概念,保证共享数据操作的完整性。每一个对象都对应一个称为“互斥锁”的 标记,这个标记保证了在任何时刻,只能有一个线程访问此对象。
- 关键字synchronized来与对象的互斥锁联系。当某个对象使用synchronized关键字修饰时,表示此对象在任何时刻,只能有一个线程访问。
synchronized案例
/**
*
*/
package com.frankstar.Thread;
/**
* @author frankstar
* 测试同步
*
*/
public class SyncThread implements Runnable{
Timer timer = new Timer();
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SyncThread st = new SyncThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.setName("frank");
t2.setName("star");
t1.start();
t2.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
timer.add(Thread.currentThread().getName());
}
}
class Timer {
private static int num = 0;
public /*synchronized */void add(String name) {
//在声明方法时加入synchronized表示执行这个方法的过程中当前对象被锁定
synchronized(this) {
//锁定当前对象
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + ": 你是第" + num + "个使用timer");
}
}
}
线程锁定 解决线程死锁的问题最好只锁定一个对象,不要同时锁定两个对象
/**
*
*/
package com.frankstar.Thread;
/**
* @author frankstar
* 线程死锁问题
*/
public class LockThread implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LockThread lt1 = new LockThread();
LockThread lt2 = new LockThread();
lt1.flag = 1;
lt2.flag = 0;
Thread t1 = new Thread(lt1);
Thread t2 = new Thread(lt2);
t1.setName("frank");
t2.setName("star");
t1.start();
t2.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName() + " flag = " + flag);
// 这里的两个if语句都将无法执行,因为已经造成了线程死锁的问题
// flag=1这个线程在等待flag=0这个线程把对象o2的锁解开,
// 而flag=0这个线程也在等待flag=1这个线程把对象o1的锁解开
// 然而这两个线程都不愿意解开锁住的对象,所以就造成了线程死锁的问题
if (flag == 1) {
synchronized (o1) { //锁定o1对象 只有o1这个线程对象执行完毕才会释放锁
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o2) {
// 前面已经锁住了对象o1,只要再能锁住o2,那么就能执行打印出1的操作了
// 可是这里无法锁定对象o2,因为在另外一个flag=0这个线程里面已经把对象o1给锁住了
// 尽管锁住o2这个对象的线程会每隔500毫秒睡眠一次,可是在睡眠的时候仍然是锁住o2不放的
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (o2) { //锁定o2对象 只有o2这个线程对象执行完毕才会释放锁
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o1) {
// 前面已经锁住了对象o1,只要再能锁住o2,那么就能执行打印出1的操作了
// 可是这里无法锁定对象o2,因为在另外一个flag=0这个线程里面已经把对象o1给锁住了
// 尽管锁住o2这个对象的线程会每隔500毫秒睡眠一次,可是在睡眠的时候仍然是锁住o2不放的
System.out.println("1");
}
}
}
}
}
线程案例
/**
*
*/
package com.frankstar.Thread;
/**
* @author frankstar
* 生产者-消费者问题
* 1.共享数据的不一致性/临界资源的保护
* 2.java对象锁的概念
* 3.synchronized关键字/wait() notify()
*/
public class ProducerConsumer {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SyncStack ss = new SyncStack();
Runnable p = new Producer(ss);
Runnable c = new Consumer(ss);
Thread p1 = new Thread(p);
Thread c1 = new Thread(c);
p1.start();
c1.start();
}
}
class SyncStack {
//支持多线程同步操作的堆栈实现
private int index = 0;
private char []data = new char[6];
public synchronized void push (char c) {
if (index == data.length) {
try {
this.wait();
} catch (InterruptedException e) {}
}
this.notify();
data[index] = c;
index++;
}
public synchronized char pop() {
if (index == 0) {
try {
this.wait();
} catch (InterruptedException e) {}
}
this.notify();
index--;
return data[index];
}
}
class Producer implements Runnable {
SyncStack stack;
public Producer (SyncStack s) {
stack = s;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++){
char c = (char)(Math.random()*26 + 'A');
stack.push(c);
System.out.println("生产: " + c);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e){
}
}
}
}
class Consumer implements Runnable {
SyncStack stack;
public Consumer(SyncStack s) {
stack = s;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 10; i++) {
char c = stack.pop();
System.out.println("消费: " + c);
try {
Thread.sleep((int) (Math.random()*1000));
} catch (InterruptedException e) {
}
}
}
}