线程同步
实现:
Sychronized(){
同步代码块
}
工作原理:
1)任意的对象都可以作为一个锁对象,每一对象都有一个内置锁
2) 某一时刻,锁对象最多只能被一个线程持有
3)线程获得了锁之后会一直持有,知道执行完同步代码块后才能释放。
4) 线程要执行同步代码块,必须先获得锁对象
线程不安全举例:
/**
* 线程安全问题
* 以下的做法会出现线程不安全的问题
* @author kiosk
*/
public class Ticket extends Thread{
private static int num = 100;
@Override
public void run() {
while (true) {
if (num == 0) {
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "窗口卖出了第" + num-- + "号票");
}
}
}
解决的方法:让他们有一个共同的类的字节码的锁对象
public class Ticket extends Thread{
private static int num = 100;
@Override
public void run() {
synchronized (Ticket.class){
while (true) {
if (num == 0) {
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "窗口卖出了第" + num-- + "号票");
}
}
}
}
线程休眠
sleep方法(会抛出异常),让线程休眠一会儿
/**
* @author kiosk
*/
public class Demo2 {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i);
}
}
}.start();
new Thread(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
(1)sleep方法
根据源码发现,sleep是一个本地方法,
源码:
守护线程
守护线程:该线程不会单独执行,当其他的非守护线程执行完毕之后,守护线程会自动退出。具有最低级别的优先级,主要是为其他的优先级高的线程进行服务。
方法:
void setDaemon(boolean on) 当参数为true的时候,线程为守护线程
public final void setDaemon(boolean on) {
//判断当前的线程是否有权修改该线程
checkAccess();
//如果该线程还活着,那就抛出异常
if (isAlive()) {
throw new IllegalThreadStateException();
}
// on为true时候,就将这个线程标志为守护线程
daemon = on;
}
举例:
public class Deamon {
public static void main(String[] args) {
Thread t1 = new Thread("这是一个非守护线程") {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "for循环的第" + i + "次");
}
}
};
Thread t2 = new Thread("这是一个守护线程") {
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(Thread.currentThread().getName() + "for循环的第" + i + "次");
}
}
};
//将线程设置为守护线程,当非守护线程执行完毕的时候,守护线程就会退出
t2.setDaemon(false);
t1.start();
t2.start();
}
}
加入线程
相当于是插队 join() 方法,会抛出异常(InterruptedException)
举例:两个线程中,在一个线程执行的过程中另一个线程加入,先让加入的线程执行完毕,相当于是抢占资源。
源代码:
//用来加入当前线程(规定的时间)
public final synchronized void join(long millis)
throws InterruptedException {
//获得当前时间
long base = System.currentTimeMillis();
//
long now = 0;
//时间负数的话那么这个抛出异常
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
//如果参数为零的话,一直等待
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
//如果线程为还活着
while (isAlive()) {
//时间到,就会退出
long delay = millis - now;
if (delay <= 0) {
break;
}
//进入wait状态
wait(delay);
//now为从记录base开始之后过去的时间
now = System.currentTimeMillis() - base;
}
}
}
举例:
public class TestJoin {
public static void main(String[] args) {
final Thread t1 = new Thread("线程1"){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "1111");
}
}
};
Thread t2 = new Thread("线程2"){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 2){
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "2222");
}
}
};
t1.start();
t2.start();
}
}
礼让线程
礼让线程(很少使用)让出CPU
public class TestYied {
public static void main(String[] args) {
new Thread("线程1") {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--" + i);
}
}
}.start();
new Thread("礼让线程") {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if (i % 2 == 0){
//如果是偶数,进行谦让
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + "--" + i );
}
}
}.start();
}
}
设置线程优先级
public final void setPriority(int newPriority)
public class TestPriority {
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+ "aaaa");
}
}
};
Thread t2 = new Thread(){
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+ "bbbb");
}
}
};
//设置最大优先级 能让当前线程优先执行
t1.setPriority(10);
//设置最小优先级
t2.setPriority(1);
t1.start();
t2.start();
}
}
之前线程安全类的回顾
Vector:线程安全 ArrayList :线程不安全的
HashMap :线程安全 HashTable :线程安全
StringBuffer:线程安全 StringBuilder:线程不安全
Collections:集合工具类能将线程不安全的集合转换为线程安全的集合