继承thread类实现多线程
package com.bxy.thread;
class MyThread extends Thread{
private String title;
public MyThread(String title) {
this.title=title;
}
public void run() {
System.out.println("线程启动");
for(int i=0;i<10;i++) {
System.out.println("x="+i);
}
}
}
public class JavaDemo {
public static void main(String[] args) {
MyThread thread1=new MyThread("线程1");
MyThread thread2=new MyThread("线程2");
MyThread thread3=new MyThread("线程3");
thread1.start();
thread2.start();
thread3.start();
}
}
实现Runnable接口实现多线程
package com.bxy.thread;
class MyThread implements Runnable{
private String title;
public MyThread(String title) {
this.title=title;
}
public void run() {
System.out.println(title+"启动");
for(int i=0;i<10;i++) {
System.out.println("x="+i);
}
}
}
public class JavaDemo {
public static void main(String[] args) {
Thread thread1=new Thread(new MyThread("线程1"));
Thread thread2=new Thread(new MyThread("线程2"));
Thread thread3=new Thread(new MyThread("线程3"));
thread1.start();
thread2.start();
thread3.start();
}
}
使用lambda(匿名函数)实现多线程定义
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
String title = “线程” + i;
Runnable run = () -> {
for (int j = 1; j <= 10; j++) {
System.out.println(title + “运行喽,y=” + j);
}
};
new Thread(run).start();
}
}
简化代码
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
String title = “线程” + i;
new Thread(() -> {
for (int j = 1; j <= 10; j++) {
System.out.println(title + “运行喽,y=” + j);
}
}).start();
}
}
实现Callable接口实现多线程
package com.bxy.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyThread implements Callable{
private String name;
public MyThread(String name) {
this.name=name;
}
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
System.out.println(name+"正在开始执行😀");
for(int i=0;i<10;i++) {
System.out.println("线程正在执行,x="+i);
}
return "线程"+name+"执行完毕😗";
}
}
public class JavaDemo {
public static void main(String[] args) {
FutureTask<String> task1=new FutureTask<String>(new MyThread("线程ONE"));
FutureTask<String> task2=new FutureTask<String>(new MyThread("线程TWO"));
FutureTask<String> task3=new FutureTask<String>(new MyThread("线程THREE"));
new Thread(task1).start();
new Thread(task2).start();
new Thread(task3).start();
}
}
获取线程名称,对单个线程进行控制
(使用Thread.currentThread().getName()//获取线程名称)
package com.bxy.thread;
class MyThread implements Runnable {
@Override
public void run() {
System.out.println(“当前的线程对象是”+Thread.currentThread().getName());
}
}public class JavaDemo {
public static void main(String[] args) {
MyThread mt=new MyThread();
mt.run();
new Thread(mt,"线程1").start();
new Thread(mt).start();
new Thread(mt,"线程2").start();
}
}
所有线程是在一个主线程中实现调用,相当于主线程去分配任务,自己不去干一些浪费事件的事情
线程的休眠
(使用Thread.sleep()对线程进行休眠)
、 public static void main(String[] args) {
MyThread mt = new MyThread();
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
for (int j = 0; j <= 10; j++) {
System.out.println(Thread.currentThread().getName() + "j=" + j);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "线程对象" + i).start();
;
}
}
运行后会发现 这5个线程好像是同时进入休眠,又同时进行启动,但实际上并不是如此,线程总会有一个先来后到,但不排除,运行很快时,出现线程同步的事件
线程中断
(使用thread.interupet()对线程进行中断)
线程中断会抛出线程中断异常
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
try {
System.out.println("奋斗了三天三夜,我要睡觉啦");
Thread.sleep(10000);
System.out.println("哇,一觉睡醒了的感觉真好");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("不嘛,/(ㄒoㄒ)/~~,我还要接着睡嘛");
}
});
thread.start();
Thread.sleep(1000);
if(!thread.isInterrupted()) {
System.out.println("毕大宇,起床吃饭啦!");
thread.interrupt();
}
}
线程的强制执行
通过 mainThread.join() 表示mainThread这个线程要加入进来啦,而且是独占。
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();
Thread thread=new Thread(()->{
for(int i=0;i<=100;i++) {
if(i==3) {
System.out.println("我要开始霸道起来啦");
try {
mainThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"执行中,i="+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"玩耍的线程");
thread.start();
System.out.println("我要开始霸道起来啦");
for(int i=0;i<=100;i++) {
System.out.println("老子是霸道的线程,我要捏碎你i="+i);
Thread.sleep(100);
}
}
线程的礼让
(使用Thread.yield()方法,礼让当前线程,让别的线程先去执行)
礼让执行的时候每一次调用yield()方法都只会礼让一次当前的资源
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();
Thread thread=new Thread(()->{
for(int i=0;i<=100;i++) {
if(i%3==0) {
Thread.yield();
System.out.println("我讲礼貌的,你👍,你先来");
}
System.out.println(Thread.currentThread().getName()+"执行中,i="+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"玩耍的线程");
thread.start();
for(int i=0;i<=100;i++) {
System.out.println("老子是霸道的线程,我要捏碎你i="+i);
Thread.sleep(100);
}
}
线程的优先级
设置优先级后,只是提高了可能性,并不是确定的优先级
public static void main(String[] args) throws InterruptedException {
Runnable run=()->{
for(int i=1;i<=10;i++) {
System.out.println(Thread.currentThread().getName()+"执行i="+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Thread threadA=new Thread(run,"线程A");
Thread threadB=new Thread(run,"线程B");
Thread threadC=new Thread(run,"线程C");
threadA.setPriority(Thread.MAX_PRIORITY);
threadB.setPriority(Thread.MIN_PRIORITY);
threadC.setPriority(Thread.MIN_PRIORITY);
threadA.start();
threadB.start();
threadC.start();
}
线程同步问题的引出
package com.bxy.thread;
class MyThread implements Runnable {
private int ticket=10;
public void run() {
while(true) {
if(ticket>0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+"卖票,票数还剩"+ticket--);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
System.out.println("------------不好意思,票已经卖完啦--------------");
break;
}
}
}
}
public class JavaDemo {
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();
}
}
运行代码后会出现票数为0,甚至-1的情况出现,为什么呐?
因为run()方法中加入了sleep()方法,使线程进入了休眠,我们可以知道当票数等于1时,会进入if判断,并且该线程会进入休眠状态。此时,该线程并未重新启动时(相应的不会去执行–的操作,所以票数也没有更改),而另一个线程的票数仍然是1,所以该线程继续进入了if判断。。。。。。
所以,当多个线程访问同一资源时,如何解决数据的完整性,就成了一个问题?
线程同步
synchronized关键字便可以实现线程的同步处理,但同步处理会降低性能,synchronized相当于一个房间,只能允许一个线程进入,当房间里有线程存在时,别的线程只能够等待,想进来可以,等我出来。
class MyThread implements Runnable {
private int ticket=10;
public synchronized boolean sales() {
if(ticket>0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+"卖票,票数还剩"+ticket--);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}else {
System.out.println("------------不好意思,票已经卖完啦--------------");
return false;
}
}
public void run() {
while(this.sales()) {
}
}
}
public class JavaDemo {
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();
}
}
线程死锁
package com.bxy.thread;
import com.sun.org.apache.xerces.internal.parsers.CachingParserPool.SynchronizedGrammarPool;
public class JavaDemo implements Runnable{
private LiHuiHui lhh=new LiHuiHui();
private BiXingYu bxy=new BiXingYu();
public static void main(String[] args) {
new JavaDemo();
}
public JavaDemo() {
new Thread(this).start();
bxy.say(lhh);
}
@Override
public void run() {
// TODO Auto-generated method stub
lhh.say(bxy);
}
}
class LiHuiHui{
public synchronized void say(BiXingYu bxy) {
System.out.println("lhh:此路是我开,此树是我栽,想要从这过,留下两毛钱");
bxy.get();
}
public synchronized void get() {
System.out.println("lhh:哈哈哈,买仔仔棒吃去喽");
}
}
class BiXingYu{
public synchronized void say(LiHuiHui lhh) {
System.out.println(“bxy:你先让我过去,我再给你钱嘛”);
lhh.get();
}
public synchronized void get() {
System.out.println(“bxy:哼,乘机赶紧跑咯”);
}
}
死锁造成的主要原因是因为彼此都在互相等待着,等待着对方先让出资源。死锁实际上是一种开发中不确定的状态,有的时候,代码处理不当则会不定期出现死锁,这是属于正常开发中的调试问题.
若干个线程访问统一资源是一定要进行同步处理,而过多的同步会造成死锁。