三个方法:构造方法设置,setName方法,getName方法
示例:
static class Mythread implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
//获取当前线程名称
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args){
Mythread mt = new Mythread();
new Thread(mt,"线程A").start();//手动命名 --线程A
new Thread(mt).start();//自动命名 --Thread-0
mt.run();//输出主线程你名称 (从输出结果也能看出先运行的是主线程)--main
}
示例:
public static void main(String[] args){
Runnable run = () -> {
for(int x = 0; x < 10 ; x++) {
System.out.println(Thread.currentThread().getName() + ",x="+x);
try {
Thread.sleep(1000);//暂缓1秒执行
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
for(int num = 0 ;num < 5 ;num ++) {
new Thread(run,"线程对象" + num).start();
}
}
方法 | 描述 |
---|---|
public boolean isInterrupted() | 判断线程是否被中断 |
public void interrupt() | 中断线程执行 |
public static void main(String[] args) throws Exception{
Thread thread = new Thread(() -> {
System.out.println("[BEFORE]准备睡觉10s,不要打扰我");
try {
Thread.sleep(10000);
System.out.println("[FINISH]睡醒了,准备工作和学习");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
thread.start();
Thread.sleep(1000);//保证子线程先运行1s
if(!thread.isInterrupted()) {
System.out.println("[INTERRUPT]敲锣打鼓惊天洗地地经过你睡觉的地方");
thread.interrupt();
}
}
public final void join() throws InterruptedException
public static void main(String[] args) throws Exception{
Thread mainThread = Thread.currentThread();//获得主线程
Thread thread = new Thread(() -> {
for(int i =0 ; i< 100 ; i++) {
if( i == 3) {
try {
mainThread.join();//强制执行线程任务
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行x:"+i);
}
},"玩耍的线程");
thread.start();
for(int x =0 ; x< 100 ; x++) {
thread.sleep(100);
System.out.println("[霸道的main线程] number = " +x);
}
}
在 i<3时,两个线程会交替执行,而当i=3时,会在主线程执行完毕后再执行子线程
public static void yield()
public static void main(String[] args) throws Exception{
Thread thread = new Thread(() ->
{
for(int x = 0 ;x < 100 ; x++) {
if(x % 3 == 0 ) {
Thread.yield();//线程礼让
System.out.println("[YIELD]线程礼让"+Thread.currentThread().getName());
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行x:"+x);
}
},"玩耍的线程");
thread.start();
for(int x = 0 ;x < 100; x++ ) {
Thread.sleep(100);
System.out.println("[霸道的main线程] number:"+x);
}
}
方法 | 描述 |
---|---|
public static final int MAX_PRIORITY | 最高优先级,数值为10 |
public static final int NORM_PRIORITY | 中等优先级,数值为5 |
public static final int MIN_PRIORITY | 最低优先级,数值为1 |
public final void setPriority(int NewPriority) | 设置线程优先级 |
public final int getPriority | 取得线程优先级 |
主方法的优先级为5
public static void main(String[] args) throws Exception{
Runnable run = () -> {
for(int x = 0 ; x < 10 ; x++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行。");
}
};
Thread threadA = new Thread(run,"线程A");
Thread threadB = new Thread(run,"线程B");
Thread threadC = new Thread(run,"线程C");
//设置优先级,理论上优先级越高越有可能抢占资源
threadA.setPriority(Thread.MIN_PRIORITY);
threadB.setPriority(Thread.NORM_PRIORITY);
threadC.setPriority(Thread.MAX_PRIORITY);
threadA.start();
threadB.start();
threadC.start();
}
static class Mythread implements Runnable{
private int ticket = 3;
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {//持续卖票
if(this.ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("卖票 ticket:"+this.ticket --);
}else {
System.out.println("****票已经卖光了****");
break;
}
}
}
}
public static void main(String[] args) throws Exception{
Mythread mt = new Mythread();
new Thread(mt,"售票员A").start();
new Thread(mt,"售票员B").start();
new Thread(mt,"售票员C").start();
}
会观察到票被重复卖了
所以提出同步的概念
使用synchronized关键字实现同步处理
使用同步代码块,为代码加“锁“:
static class Mythread implements Runnable{
private int ticket = 3;
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {//持续卖票
synchronized(this) {//同步代码块
if(this.ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+
"卖票 ticket:"+this.ticket --);
}else {
System.out.println("****票已经卖光了****");
break;
}
}
}
}
}
public static void main(String[] args) throws Exception{
Mythread mt = new Mythread();
new Thread(mt,"售票员A").start();
new Thread(mt,"售票员B").start();
new Thread(mt,"售票员C").start();
}
但是同步会造成处理i性能的下降,也带来一些优点:数据的进程访问安全
static class Mythread implements Runnable{
private int ticket = 3;
@Override
public void run() {
// TODO Auto-generated method stub
while(this.sale()) {
}
}
public synchronized boolean sale() {
if(this.ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+
"卖票 ticket:"+this.ticket --);
return true;
}else {
System.out.println("****票已经卖光了****");
return false;
}
}
}
public static void main(String[] args) throws Exception{
Mythread mt = new Mythread();
new Thread(mt,"售票员A").start();
new Thread(mt,"售票员B").start();
new Thread(mt,"售票员C").start();
}
static class Book{
public synchronized void tell(Painting painting) {
System.out.println("张三对李四说:把画给我,我就给你书,不给画不给书");
painting.get();
}
public synchronized void get() {
System.out.println("张三获得了李四的画");
}
}
static class Painting{
public synchronized void tell(Book book) {
System.out.println("李四对张三说:把书给我,我就给你画,不给书不给画");
book.get();
}
public synchronized void get() {
System.out.println("李四获得了张三的书");
}
}
static class DeadLock implements Runnable{
private Book book = new Book();
private Painting painting = new Painting();
public DeadLock() {
// TODO Auto-generated constructor stub
new Thread(this).start();
book.tell(painting);
}
@Override
public void run() {
// TODO Auto-generated method stub
painting.tell(book);
}
}
public static void main(String[] args) throws Exception{
new DeadLock();//程序一直等待
}
static class Message{
private String title;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
static class Producer implements Runnable{
private Message msg = null;
public Producer(Message msg) {
// TODO Auto-generated constructor stub
this.msg = msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int x = 0 ;x < 50 ; x++) {
if(x % 2 == 0) {
this.msg.setTitle("孔夫子");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.msg.setContent("儒家学术");
}else {
this.msg.setTitle("老子");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.msg.setContent("道家学术");
}
}
}
}
static class Consumer implements Runnable{
private Message msg;
public Consumer(Message msg) {
// TODO Auto-generated constructor stub
this.msg = msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int x = 0 ; x< 50 ; x++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.msg.getTitle()+"-->"+this.msg.getContent());
}
}
}
public static void main(String[] args) throws Exception{
Message msg = new Message();
new Thread(new Producer(msg)).start();
new Thread(new Consumer(msg)).start();
}
可以看到最后是有个
数据错位和重复操作的问题
解决数据同步问题
static class Message{
private String title;
private String content;
public synchronized void set(String title,String content) {
this.title = title;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.content = content;
}
public synchronized String get() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this.title+"-->"+this.content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
static class Producer implements Runnable{
private Message msg = null;
public Producer(Message msg) {
// TODO Auto-generated constructor stub
this.msg = msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int x = 0 ;x < 50 ; x++) {
if(x % 2 == 0) {
this.msg.set("孔夫子", "儒家学派");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
this.msg.set("老子", "道家学派");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable{
private Message msg;
public Consumer(Message msg) {
// TODO Auto-generated constructor stub
this.msg = msg;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int x = 0 ; x< 50 ; x++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.msg.get());
}
}
}
public static void main(String[] args) throws Exception{
Message msg = new Message();
new Thread(new Producer(msg)).start();
new Thread(new Consumer(msg)).start();
}
方法 | 描述 |
---|---|
public final void wait() throws InterruptedException | 线程等待 |
public final void wait(long timeout) throws InterruptedException | 设置等待毫秒数 |
public final void wait(long timeout,int nanos) throws InterruptedException | 设置等待毫秒数和纳秒数 |
public final void notify() | 唤醒第一个等待线程 |
public final void notifyAll() | 唤醒所有等待线程 |
示例:
static class Message{
private String title;
private String content;
private boolean flag = true;
//true表示允许生产,不允许消费
//false表示允许消费,不允许生产
//set表示生产过程
public synchronized void set(String title,String content) {
if(this.flag == false) {//无法进行生产,等待被消费
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.title = title;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.content = content;
this.flag = false;
super.notify();
}
//get表示消费过程
public synchronized String get() {
if(this.flag == true) {//还未生产
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
return this.title +"->"+ this.content;
} finally {
// TODO: handle finally clause
this.flag = true;//继续生产
super.notify();
}
}
}
停止线程的3个方法:
suspend(),resume(),stop()方法从jdk1.2以来就不推荐使用了,因为这三个方法可能会产生死锁
优雅地停止线程运行
public class testDemo {
public static boolean flag = true;
public static void main(String[] args) throws Exception {
new Thread (() ->{
long num = 0;
while(flag) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在运行"+num);
}
},"执行线程").start();
Thread.sleep(100);
flag = false;
}
}
定义:随用户线程存在而存在,随用户线程消失而消失
方法 | 描述 |
---|---|
public final void setDaemon(boolean on) | 设置为守护线程 |
public final boolena isDaemon | 判断是否为守护线程 |
public static void main(String[] args) {
Thread userThread = new Thread(() ->
{
for(int x = 0 ;x < 2 ;x++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在执行x:"+x);
}
},"用户线程");
Thread daemonThread = new Thread(() ->
{
for(int x = 0 ;x < 100 ;x++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在执行x:"+x);
}
},"守护线程");
daemonThread.setDaemon(true);
userThread.start();
daemonThread.start();
}
定义:多线程中为实现公共资源的操作,通常都是复制变量副本再同步,
而在变量声明时使用volatile关键字,就可以节约复制变量副本和同步的时间
static class Mythread implements Runnable {
private volatile int ticket = 3;
@Override
public void run() {
// TODO Auto-generated method stub
synchronized(this) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket --);
}
}
}
public static void main(String[] args) {
Mythread mt = new Mythread();
new Thread(mt,"售票员A").start();
new Thread(mt,"售票员B").start();
new Thread(mt,"售票员C").start();
}