继承Thread
案例
public static void main(String[] args) {
MyThread m = new MyThread();
m.start();
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
public class MyThread extends Thread{
public void run(){
//这里的代码就是一条新的执行路径
//通过thread对象start()来启动任务
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
实现Runnable
案例
public static void main(String[] args) {
/**
* 与Thread相比
* 1 通过创建任务,给线程分配的方式 , 适合多个线程执行相同任务
* 2 避免单继承所带来的局限性(Java允许多实现,不允许多继承)
* 3 任务与线程本身分离
* 4 * 后续的线程池,接受Runnable类型的任务,不接受Thread
*/
//实现Runnable
//1 创建任务对象
Myrunnable r = new Myrunnable();
//2 创建线程,分配任务
Thread t = new Thread(r);
//3 执行
t.start();
for(int i = 0;i<10;i++){
System.out.println("疑是地上霜"+i);
}
//匿名内部类写法
new Thread(){ //仍是继承Thread的方式
public void run(){
for(int i = 0;i<10;i++){
System.out.println("12345"+i);
}
}
}.start();
}
public class Myrunnable implements Runnable{
public void run(){
//线程任务
System.out.println(Thread.currentThread().getName());
for (int i = 0; i < 5; i++) {
System.out.println("床前明月光"+i);
}
}
}
获取线程名称
Thread.currentThread().getName() 返回String类型
线程中断
t.interrupt ()
public static void main(String[] args) {
Thread t1 = new Thread(new Myrunnable2());
t1.setDaemon(true); // 设置守护线程
t1.start();
for(int i=1;i<3;i++){
System.out.println(Thread.currentThread().getName()+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) { //线程中断源异常
e.printStackTrace();
}
}
//给线程t1添加中断标记
t1.interrupt();
}
static class Myrunnable2 implements Runnable{
@Override
public void run() {
for(int i=1;i<10;i++){
System.out.println(Thread.currentThread().getName()+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
//发现终端标记,线程自杀
System.out.println("发现中断标记,自杀");
return;
}
}
}
}
线程不安全
1.同步代码块
synchronized(锁对象){ 同步代码 }
需同步的线程在run中共用一个
public static void main(String[] args) {
//线程不安全
//解决方案 1.同步代码块
// synchronized(锁对象){ 同步代码 }
Runnable run = new Ticket();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
static class Ticket implements Runnable{
//票数
private int count = 10;
Object o = new Object(); // 锁对象,互斥线程必须用同一个
public void run(){
while (true) {
synchronized (o) { //同步代码块
if (count > 0) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,剩余" + count);
}else{
break;
}
}
}
}
}
2.同步方法
用synchronized修饰的方法
static class Ticket implements Runnable{
//票数
private int count = 10;
public void run(){
while (true){
//卖票
boolean flag = sale();
if(!flag){
break;
}
}
}
public synchronized boolean sale(){ //排队运行方法
if (count > 0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,剩余"+count);
return true;
}
return false;
}
}
3. *显式锁
Lock的子类 ReentrantLock
public static void main(String[] args) {
//线程不安全
// 方案3 显式锁
// Lock的子类 ReentrantLock
Runnable run = new Ticket();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
static class Ticket implements Runnable{
//票数
private int count = 10;
private Lock l = new ReentrantLock(true); //参数为true,则是公平锁,先来先得
public void run(){
while (true) {
l.lock(); //锁住
if (count > 0) {
//卖票
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,剩余" + count);
}else{
break;
}
l.unlock();
}
}
}
生产者消费者问题案例
用一个boolean flag来限制操作
this.notify () 唤醒此进程所有线程
this.wait () 等待唤醒
public static void main(String[] args) {
Food f = new Food();
new Cook(f).start();
new Waiter(f).start();
}
//厨师
static class Cook extends Thread{
private Food f;
public Cook(Food f) {
this.f = f;
}
@Override
public void run() {
for(int i=0;i<100;i++){
if(i%2==0){
f.setNameAndStaste("小米粥\t","清淡");
}else{
f.setNameAndStaste("煎饼果子\t","甜辣味");
}
}
}
}
//服务生
static class Waiter extends Thread{
private Food f;
public Waiter(Food f) {
this.f = f;
}
@Override
public void run() {
for(int i=0;i<100;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
f.get();
}
}
}
//食物
static class Food{
private String name;
private String taste;
private boolean flag = true;
//true表示可以生产
public synchronized void setNameAndStaste(String name,String taste) {
if (flag) {
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.taste = taste;
flag = false;
this.notify();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void get() {
if (!flag) {
System.out.println("服务员上菜,菜名:" + name + "味道:" + taste);
flag = true;
this.notify();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这篇博客详细介绍了Java中线程的实现方式,包括继承Thread类和实现Runnable接口,并通过实例展示了线程同步、线程池以及生产者消费者问题的解决方法。此外,还讨论了线程安全问题及其解决方案,如同步代码块、同步方法和显式锁的使用。最后,提到了线程池的重要性和应用。
1448

被折叠的 条评论
为什么被折叠?



