1.创建线程的两种方式
1.1通过继承Thread,重写run方法
package com.yanzi.chapter1;
//第一种创建线程的方法:通过继承Thread,重写run方法
public class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("MyThread:"+i);
}
}
}
package com.yanzi.chapter1;
public class Demo01_CreateThred{
public static void main(String[] args) {
//获取当前线程
Thread mainThread = Thread.currentThread();
MyThread thread = new MyThread();
//打印查看线程优先级
System.out.println(thread.getPriority());
//设置线程优先级,优先级范围为1~10,数字越大,优先级越高,默认为5(抢占式调度规则)
mainThread.setPriority(10);
//开启线程
thread.start();
for(int i=0;i<10000;i++) {
System.out.println("MainThread:"+i);
}
}
}
1.2多个线程的开启,线程命名,线程休眠,线程合并,守护线程,设置线程中止状态
package com.yanzi.chapter1;
//第一种创建线程的方法:通过继承Thread,重写run方法
public class MyThread extends Thread{
public MyThread() {}
public MyThread(String string) {
// TODO Auto-generated constructor stub
}
@Override
public void run() {
for(int i=0;i<10000;i++) {
if(interrupted()) {
System.out.println("释放资源!");
break;
}
System.out.println(getName()+":"+i);
}
}
}
package com.yanzi.chapter1;
public class Demo02_Thread {
public static void main(String[] args) throws Exception {
线程休眠2000毫秒,在这里暂停2秒
//Thread.sleep(2000);
MyThread t1 = new MyThread("线程1");
//开启线程
t1.start();
//设置线程状态为中断状态,返回布尔值,在线程中进行判断操作
t1.interrupt();
//t1合并到当前线程,但t1仍会继续执行
//t1.join();
MyThread t2 = new MyThread("线程2");
//设置守护线程,要在线程启用之前设置
t2.setDaemon(true);
t2.start();
}
}
1.3通过Runnable接口实现线程(优点是数据共享,继承方便)
package com.yanzi.chapter1;
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int i=0;i<1000;i++) {
Thread t = Thread.currentThread();
System.out.println(t.getName()+":"+i);
}
}
}
package com.yanzi.chapter1;
public class Demo03_CreateThreadMethod2 {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t1 = new Thread(r,"线程1");
t1.start();
Thread t2 = new Thread(r,"线程2");
t2.start();
}
}
线程安全问题:锁
四个窗口卖票小案例:使用锁保证线程安全
package com.yanzi.chapter1;
public class Demo04_TicketSell {
public static void main(String[] args) {
TicketRunnable tr = new TicketRunnable();
Thread t1 = new Thread(tr,"售票点1");
Thread t2 = new Thread(tr,"售票点2");
Thread t3 = new Thread(tr,"售票点3");
Thread t4 = new Thread(tr,"售票点4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
package com.yanzi.chapter1;
public class TicketRunnable implements Runnable {
private int count=100;
//设置一个锁,要保证锁是同一个锁
private Object lock = new Object();
@Override
public void run() {
while(true) {
synchronized (lock) {
if(count>0) {
System.out.println(Thread.currentThread().getName()+"卖出"+count+"票");
count--;
}else {
break;
}
}
}
}
}
另一种写法:
package com.yanzi.chapter1;
public class TicketRunnable implements Runnable {
private int count=100;
//设置一个锁,要保证锁是同一个锁
private Object lock = new Object();
@Override
public void run() {
while(true) {
sellTicket();
}
}
public synchronized void sellTicket() {
if(count>0) {
System.out.println(Thread.currentThread().getName()+"卖出"+count+"票");
count--;
}
}
}
第二种加锁的方式:ReentrantLock
package com.yanzi.chapter1;
import java.util.concurrent.locks.ReentrantLock;
public class TicketRunnable implements Runnable {
private int count=100;
//设置一个锁,要保证锁是同一个锁
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while(count>0) {
lock.lock();
try {
if(count>0) {
System.out.println(Thread.currentThread().getName()+"卖出"+count+"票");
count--;
}
} finally{
lock.unlock();
}
}
}
}
死锁:多个线程同时被阻塞,他们中的一个或者全部都在等待资源被释放,由于线程被无限期的阻塞,因此程序不能正常中止。
解决死锁:拿钥匙的顺序保持一致即可。
线程组:
package com.yanzi.chapter1;
public class Demo08_ThreadGroup {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
//给线程组命名
ThreadGroup tg = new ThreadGroup("我的线程组");
Thread t1 = new Thread(tg,r);
System.out.println(t1.getThreadGroup().getName());
t1.start();
}
}
定时器:
package com.yanzi.chapter1;
import java.util.Timer;
public class Demo04_TicketSell {
public static void main(String[] args) {
Timer t =new Timer();
t.schedule("要执行的任务", "延迟的时间");
//取消定时器
t.cancel();
}
}