创建线程
public class Thread01 {
public static void main(String[] args) {
//创建Cat对象,可以当做线程使用
Cat cat = new Cat();
//启动线程
cat.start();
}
}
//当一个类继承了Thread类,改类就可以做线程使用
class Cat extends Thread{
@Override
public void run() {
System.out.println("喵喵喵");
}
}
public class Thread02 {
public static void main(String[] args) {
Cat cat = new Cat();
//将实现Runnable接口的类放入Thread(使用了代理模式)
Thread t = new Thread(cat);
t.start();
}
}
//实现Runnable接口
class Cat implements Runnable{
public void run() {
System.out.println("喵喵喵");
}
}
public class SellTicket{
public static void main(String[] args) {
//创建三个线程
SellTicket01 thread01 = new SellTicket01();
SellTicket01 thread02 = new SellTicket01();
SellTicket01 thread03 = new SellTicket01();
//启动三个线程
thread01.start();
thread02.start();
thread03.start();
}
}
class SellTicket01 extends Thread{
//票数
private static int ticketNum = 100;
@Override
public void run() {
while (true){
if (ticketNum <= 0){
System.out.println("售票结束");
break;
}
//休眠50ms
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 "+Thread.currentThread().getName()+" 售出一张票,剩余票数 "+ (--ticketNum));
}
}
}
通知线程退出
public class Thread03 {
public static void main(String[] args) throws Exception {
Cat cat = new Cat();
cat.start();
Thread.sleep(1000);
//通知线程,通过设置Cat对象flog通知线程停止
cat.setFlog(false);
}
}
class Cat extends Thread{
private boolean flog = true;
public void setFlog(boolean flog) {
this.flog=flog;
}
@Override
public void run() {
while (flog){
System.out.println("喵喵喵");
}
}
}
线程插队
- yield:线程的让步。让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定让步成功
- join:线程的插队。插队的线程一旦插队成功,则肯定先执行完插入的线程所有任务
- 案例
- 主线程创建一个子线程,每隔1s输入hello,输出10次,主线程每个1s输出hi,输出10次
- 两个线程同时进行,当主线程输出5次后,就让子线程运行完毕,主线程再继续
public class Thread04 {
public static void main(String[] args) throws Exception {
//子线程打印10次hello
T t = new T();
t.start();
//主线程打印10次hi
for (int i =0;i<=10;i++){
Thread.sleep(1000);
System.out.println("hi " + i);
//当打印了5次时让子线程运行完毕,主线程再继续(子线程t插队)
if (i == 5){
t.join();
}
}
}
}
class T extends Thread{
@Override
public void run() {
for (int i=1;i<=10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello " + i);
}
}
}
线程同步机制
public class SellTicket{
public static void main(String[] args) {
//创建三个线程
SellTicket01 thread01 = new SellTicket01();
new Thread(thread01).start();
new Thread(thread01).start();
new Thread(thread01).start();
}
}
class SellTicket01 implements Runnable{
//票数
private static int ticketNum = 10;
private boolean loop = true;
public void run() {
while (true){
sell();
if (!loop){
break;
}
}
}
public synchronized void sell(){
if (ticketNum <= 0){
System.out.println("售票结束");
loop = false;
return;
}
//休眠50ms
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 "+Thread.currentThread().getName()+" 售出一张票,剩余票数 "+ (--ticketNum));
}
}
public class SellTicket{
public static void main(String[] args) {
SellTicket02 thread01 = new SellTicket02();
SellTicket02 thread02 = new SellTicket02();
SellTicket02 thread03 = new SellTicket02();
thread01.start();
thread02.start();
thread03.start();
}
}
class SellTicket02 extends Thread{
//票数
private static int ticketNum = 10;
private boolean loop = true;
@Override
public void run() {
while (true){
synchronized (Object.class){
if (ticketNum <= 0){
System.out.println("售票结束");
loop = false;
return;
}
//休眠50ms
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 "+Thread.currentThread().getName()+" 售出一张票,剩余票数 "+ (--ticketNum));
}
}
}
}
- 互斥锁
- Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
- 每个对象都对于一个可称为“互斥锁”的标记,这个标记用来保证在任意时刻只能有一个线程访问该对象
- 关键字synchronized来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任意时候只能由一个线程访问
- 同步的局限性:导致程序的执行效率要降低
- 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一对象)
- 同步方法(静态的)的锁为当前类本身