1.JAVA线程的两种方式:
a.继承Thread类
public class Demo2_Thread {
/**
* @param args
*/
public static void main(String[] args) {
MyThread mt = new MyThread(); //4,创建Thread类的子类对象
mt.start(); //5,开启线程
for(int i = 0; i < 1000; i++) {
System.out.println("bb");
}
}
}
class MyThread extends Thread { //1,继承Thread
public void run() { //2,重写run方法
for(int i = 0; i < 1000; i++) { //3,将要执行的代码写在run方法中
System.out.println("aaaaaaaaaaaa");
}
}
}
b.实现Runnable接口:
public class Demo3_Thread {
/**
* @param args
*/
public static void main(String[] args) {
MyRunnable mr = new MyRunnable(); //4,创建Runnable的子类对象
//Runnable target = mr; mr = 0x0011
Thread t = new Thread(mr); //5,将其当作参数传递给Thread的构造函数
t.start(); //6,开启线程
for(int i = 0; i < 1000; i++) {
System.out.println("bb");
}
}
}
class MyRunnable implements Runnable { //1,定义一个类实现Runnable
@Override
public void run() { //2,重写run方法
for(int i = 0; i < 1000; i++) { //3,将要执行的代码写在run方法中
System.out.println("aaaaaaaaaaaa");
}
}
}
c.获取当前线程名称:
public class test {
public static void main(String[] args) {
new Thread() {
public void run() {
System.out.println(getName()+"...aaaa");
}
}.start();
new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+".....bbbbbbbbbbbbb");
}
}).start();
System.out.println(Thread.currentThread().getName());
}
}
2.线程的方法
a.获取名字
通过getName()方法获取线程对象的名字
new Thread("xxx") {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa");
}
}
}.start();
b.设置名字
通过构造函数可以传入String类型的名字
Thread t2 = new Thread() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "....bb");
}
}
};
t2.setName("凤姐");
c.获取当前线程
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + "...aaaaaaaaaaaaaaaaaaaaa");
}
}
}).start();
3.线程分类
a.休眠线程
Thread.sleep(毫秒,纳秒), 控制当前线程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000
new Thread() {
public void run() {
for(int i = 0; i < 10; i++) {
System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
b.守护线程
setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出
Thread t1 = new Thread() {
public void run() {
for(int i = 0; i < 50; i++) {
System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println(getName() + "...bb");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.setDaemon(true); //将t1设置为守护线程
t1.start();
t2.start();
c.加入线程
join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
join(int), 可以等待指定的毫秒之后继续
final Thread t1 = new Thread() {
public void run() {
for(int i = 0; i < 50; i++) {
System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
public void run() {
for(int i = 0; i < 50; i++) {
if(i == 2) {
try {
//t1.join(); //插队,加入
t1.join(30); //加入,有固定的时间,过了固定时间,继续交替执行
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + "...bb");
}
}
};
t1.start();
t2.start();
d.礼让线程
yield()让出cpu
e.设置线程的优先级
setPriority()设置线程的优先级
4.线程的同步
a.什么情况下需要同步
当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
b.同步代码块
class Printer {
Demo d = new Demo();
public static void print1() {
synchronized(d){ //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
System.out.print("a");
System.out.print("b");
System.out.print("c");
System.out.print("d");
System.out.print("\r\n");
}
}
public static void print2() {
synchronized(d){
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.print("\r\n");
}
}
}
c.同步方法
class Printer {
public static void print1() {
synchronized(Printer.class){ //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
System.out.print("a");
System.out.print("b");
System.out.print("c");
System.out.print("d");
System.out.print("\r\n");
}
}
/*
* 非静态同步函数的锁是:this
* 静态的同步函数的锁是:字节码对象
*/
public static synchronized void print2() {
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.print("\r\n");
}
}
5.两个线程之间的通信
如果希望线程等待, 就调用wait()
如果希望唤醒等待的线程, 就调用notify();
这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
public class waitNotify {
public static void main(String[] args) {
printer p = new printer();
new Thread() {
public void run() {
while(true) {
try {
p.print1();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while(true) {
try {
p.print2();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
}
class printer{
private int flag = 1;
void print1() throws InterruptedException {
synchronized(this) {
if(!(flag == 1)) {
this.wait();
}
System.out.print("a");
System.out.print("b");
System.out.print("c");
System.out.print("d");
System.out.println();
flag = 2;
this.notify();
}
}
void print2() throws InterruptedException {
synchronized(this) {
if(!(flag == 2)) {
this.wait();
}
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.println();
flag = 1;
this.notify();
}
}
}
sleep方法和wait方法的区别
* sleep在同步代码块或者同步函数中,不释放锁
* wait在同步代码块或者同步函数中,释放锁
* sleep方法必须传入参数,参数其实就是时间,时间到了自动醒来
* wait方法可以传入参数,也可以不传入参数
* 如果给wait方法传入时间参数,用法与sleep相似,时间到就停止等待,但其锁对象是释放的
6.新特性的互斥锁
- 使用ReentrantLock类的newCondition()方法可以获取Condition对象
- 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法
- 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class reetrantLock {
public static void main(String[] args) {
printer2 p = new printer2();
new Thread() {
public void run() {
while(true) {
try {
p.print1();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while(true) {
try {
p.print2();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
}
class printer2{
ReentrantLock r = new ReentrantLock();
Condition d1 = r.newCondition();
Condition d2 = r.newCondition();
private int flag = 1;
void print1() throws InterruptedException {
r.lock();
if(!(flag == 1)) {
d1.await();
}
System.out.print("a");
System.out.print("b");
System.out.print("c");
System.out.print("d");
System.out.println();
flag = 2;
d2.signal();
r.unlock();
}
void print2() throws InterruptedException {
r.lock();
if(!(flag == 2)) {
d2.await();
}
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.println();
flag = 1;
d1.signal();
r.unlock();
}
}
7.线程组的概述和使用
- Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
- 默认情况下,所有的线程都属于主线程组。
- public final ThreadGroup getThreadGroup()//通过线程对象获取他所属于的组
- public final String getName()//通过线程组对象获取他组的名字
- 我们也可以给线程设置分组
- 1,ThreadGroup(String name) 创建线程组对象并给其赋值名字
- 2,创建线程对象
- 3,Thread(ThreadGroup?group, Runnable?target, String?name)
- 4,设置整组的优先级或者守护线程
- 默认情况下,所有的线程都属于主线程组。
public class threadGroup {
public static void main(String[] args) {
ThreadGroup tg = new ThreadGroup("自定义线程组");
myRunnable mr = new myRunnable();
Thread t1 = new Thread(tg, mr, "张三");
Thread t2 = new Thread(tg, mr, "李四");
System.out.println(t1.getThreadGroup().getName());
System.out.println(t2.getThreadGroup().getName());
}
}
class myRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
线程的状态

网友评论