java创建线程的两种方法:
第一种方法:继承Thread类
package Thread;
public class ThreadTest01 {
public static void main(String[] args) {
Thread01 th = new Thread01();
th.start();
// th.run();//属于方法的调用,没有开新线程。整个就一个main线程。
for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}
class Thread01 extends Thread {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}
第二种方法:实现Runnable接口
package Thread;
public class ThreadTest02 {
public static void main(String[] args) {
MyThread mr = new MyThread();
Thread th = new Thread(mr, "线程0");
//th.setDaemon(true);
th.start();
try {
th.join();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// th.run();//属于方法的调用,没有开新线程。整个就一个main线程。
Thread.currentThread().setName("主线程");
for (int i = 1; i <= 1000; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}
class MyThread implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 1000; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("守护线程");
}
/*while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("守护线程");
}*/
}
}
以下来自老师的笔记:
多线程:
程序运行时:启动了两个线程:
Main线程:调用main方法,执行main方法。
GC线程:在main线程运行时运行,回收程序运行之中的垃圾。
线程:一条执行路径。多线程完成多个功能并发并发执行的效果。
多线程之间乱系执行、同一线程内部顺序执行的。
写多线程:
1. 继承自Thread类,重写run方法。然后用Thread的start方法启动线程。
2. 实现Runnable接口,实现run方法。然后用Thread的start方法启动线程。
两种方式的区别:
1. 第一种使用简单。
2. 第二种不受java单继承的限制。一般来说,都是用第二种。
线程中常用的方法:线程中的已过时方法禁止使用。其他类中的过时方法不建议使用。
1. start:启动一个新线程。启动之后jvm会自动执行run方法。
2. run:线程启动之后执行的方法。
3. setName、getName:自动命名,Thread-0,1…
4. currentThread:得到当前运行的线程。
5. getPriority()、setPriority 得到和设置当前线程的优先级。优先级1-10,如果不指定默认是5.。理论上,谁优先级高,谁被cpu调度的可能性就大。但是优先级低的并不是不执行。资源不足的时候才有效果。
6. setDaemon:将线程置为守护线程。只能在线程start之前调用。一般用于为其他线程提供服务,比如GC。守护线程会随着其他非守护线程的结束而结束。isDaemon可以用于判断某个线程是否是守护线程。
7. sleep:让当前线程停止执行(休眠)一段时间。
8. join:如果在A线程中B线程join进来,则现在执行B的内容,直到B执行完毕才继续执行A。比如A是显示数据 B是收集收据。
9. yield:让位:让出执行权,和其他线程争夺资源,谁拿到cpu时间片谁执行。
线程的状态图:
说明 run方法结束,新线程结束。
线程相关的常用类:
1. Timer:定时器、调度器、计时器。
2. TimerTask:定时任务。
线程间的同步:本质:把异步转化为同步,把并行转为串行。
方式:
1. 同步语句块:synchronized(obj){}
2. 同步方法:在方法前加synchronized修饰符,拿到的仍然是本类对象的锁。
难点:不容易测出来。
对象锁:每个对象都有一把锁。同步锁、互斥锁。
线程同步示例:
package bank;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class Bank {
public static void main(String[] args) {
Account account = new Account();
Person1 you1 = new Person1(account);
Person1 yourGF1 = new Person1(account);
Thread thyou1 = new Thread(you1, "你");
Thread thyourGF1 = new Thread(yourGF1, "你女朋友");
thyou1.start();
thyourGF1.start();
Person2 you2 = new Person2(account);
Person2 yourGF2 = new Person2(account);
Thread thyou2 = new Thread(you2, "你");
Thread thyourGF2 = new Thread(yourGF2, "你女朋友");
thyou2.start();
thyourGF2.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("账户余额:" + account.balance);
}
}
class Account {
int balance = 2000;
Object obj1 = new Object();
Object obj2 = new Object();
public void withdraw() {
synchronized(obj1) {
int temp = balance;
temp = temp - 800;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
balance = temp;
System.out.println(Thread.currentThread().getName() + "取款后余额:"
+ balance);
}
}
public void deposit() {
synchronized(obj2) {
int temp = balance;
temp = temp + 800;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
balance = temp;
System.out.println(Thread.currentThread().getName() + "存款后余额:"
+ balance);
}
}
}
class Person1 implements Runnable {
private Account account;
public Person1(Account account) {
this.account = account;
}
@Override
public void run() {
account.withdraw();
}
}
class Person2 implements Runnable {
private Account account;
public Person2(Account account) {
this.account = account;
}
@Override
public void run() {
account.deposit();
}
}