1. Thread类
1.1 继承实现
package com.daigua20;
public class ThreadDemo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
// 修改线程名字
t1.setName("呆瓜");
// 启动任务
t1.start();
MyThread t2 = new MyThread();
// 修改线程名字
t2.setName("猪娃");
// 启动任务
t2.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + ":" + i);
}
}
}
1.2 Runnable接口实现
package com.daigua20;
public class ThreadDemo2 {
public static void main(String[] args) {
// 实例出Runnable接口子类的对象
MyThread2 r1 = new MyThread2(10);
MyThread2 r2 = new MyThread2(10);
// 用Runnable子类构造Thread类的实例
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
// start方法启动任务
t1.start();
t2.start();
}
}
// 定义Runnable接口的子类,重写run方法
class MyThread2 implements Runnable {
int num;
public MyThread2(int num) {
this.num = num;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i + num);
}
}
}
2.线程安全
2.1 资源共享导致的问题
package com.daigua20;
public class ThreadDemo3 {
public static void main(String[] args) {
TicketThread r1 = new TicketThread();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.start();
t2.start();
t3.start();
}
}
class TicketThread implements Runnable {
// 车票数量一百张
int tickets = 100;
@Override
public void run() {
while (true) {
if (tickets > 0) {
try {
Thread.sleep(100);
tickets -= 1;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets);
}
}
}
}
2.2解决方法
2.2.1 使用同步代码块
格式:
synchronized(锁对象){
//需要同步的代码
}
package com.daigua20;
/*
* synchronized:同步(锁),可以修饰代码块和方法,被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他的线程将无法访问
*
* 同步代码块:
* synchronized(锁对象){
*
* }
*
* 注意:锁对象需要被所有的线程所共享
*
*
* 同步:安全性高,效率低
* 非同步:效率高,但是安全性低
*
*/
public class ThreadDemo4 {
public static void main(String[] args) {
TicketThread2 r1 = new TicketThread2();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
class TicketThread2 implements Runnable {
// 车票数量一百张
int tickets = 100;
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
}
}
}
}
2.2.2 使用同步方法
格式:
修饰符 synchronized 返回值 方法名(){
}
package com.daigua20;
/*
* 同步方法:使用关键字synchronized修饰的方法,一旦被一个线程访问,则整个方法全部锁住,其他线程则无法访问
*
* synchronized
* 注意:
* 非静态同步方法的锁对象是this
* 静态的同步方法的锁对象是当前类的字节码对象
*/
public class ThreadDemo5 {
public static void main(String[] args) {
TicketThread3 tt = new TicketThread3();
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
Thread t3 = new Thread(tt);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t3.start();
t2.start();
t1.start();
}
}
class TicketThread3 implements Runnable {
// 车票数量一百张
static int tickets = 100;
// Object obj = new Object();
@Override
public void run() {
while (true) {
if (tickets > 0) {
// method();
method2();
}
}
}
private synchronized void method(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
private static synchronized void method2(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
}