目录
(一)定义
一个程序里不同的执行路径;
(二)如何创建一个线程
1、第一种:
a、创建一个继承Thread的类(假定类名为A),并重写Thread中的run方法;
b、构造一个A类对象(假定对象名是aa);
c、调用aa的steat方法(start方法由Thread继承而来);
class A extends Thread{//创建一个继承Thread的类
public void run() {//重写Thread中的run方法
while(true) {
System.out.println("aaaa!");
}
}
}
public class TestA {
public static void main(String[] args) {
A aa=new A();
aa.start();//调用aa的start方法,start方法生成一个新的线程,并自动调用aa的run方法
while(true){
System.out.println("bbbb!");
}
}
}
2、第二种:
a、定义一个实现Runnable接口的类(假定类名为B);
b、创建B类对象(假定为bb);
c、利用bb构建一个Thread对象(假定为tt);
Thread tt=new Thread(bb)
d、调用tt的start方法;
class B implements Runnable{
public void run() {
while(true) {
System.out.println("aaaaa!");
}
}
}
public class TestB {
public static void main(String[] args) {
B bb=new B();
Thread tt=new Thread(BB);
tt.start();
//tt.start();//抛出异常
while(true) {
System.out.println("bbbbb!");
}
}
}
3、创建线程注意事项
a、Thread中的start方法的功能就是创建一个新的线程,并自动调用该线程的run方法,直接调用run方法并不会创建一个新的线程;
b、执行一个线程就是执行该线程的run方法里面的代码;
c、执行完aa.start();后并不代表该线程会立刻被执行,aa.start();执行后只是代表该线程获得了被CPU执行的资格,由于想抢占CPU执行的线程很多,aa所对应的线程不一定能抢到;
d、一个Thread对象有且只能代表一个线程,若一个Thread对象调用两个aa.start();程序会抛出异常;
(四)Thread的常用方法
public final void setName(String name)(设置当前线程名字)
public static Thread currentThread()(返回当前正在执行的线程对象的引用)
public final void getName(String name)(返回当前线程的名字)
class A implements Runnable{
public void run() {
System.out.printf("%s正在运行\n",Thread.currentThread().getName());
}
}
public class Threadcsdn {
public static void main(String[] args) {
A aa=new A();
Thread tt1=new Thread(aa);
Thread tt2=new Thread(aa);
tt1.start();
tt1.setName("线程一");
tt2.start();
tt2.setName("线程二");
System.out.printf("%s正在运行\n",Thread.currentThread().getName());
}
执行结果:main正在运行
线程二正在运行
线程一正在运行
(五)线程的优先级
1、int getPriority();(获得线程的优先级数级)
void setPriority(int newPriority);(设置当前线程的优先级)
2、优先级由数字表示,范围1~10逐渐递增;
3、默认优先级为5,子类默认优先级与父类一样;
4、优先级高不一定优先执行,只是提高可能性。
(六)线程的休眠
1、线程的休眠是指暂停当前线程的执行,使之进入堵塞状态,待经过指定“延迟时间”后便醒来进入就绪状态;
2、public static void sleep(long millis);
3、sleep方法调用时会抛异常,需要进行抓捕;
class A extends Thread{
public void run() {
for(int i=0;i<10;i++) {
System.out.printf("%s--%d正在执行\n",Thread.currentThread().getName(),i);
try {
Thread.sleep(1000);
}
catch(Exception e) {
}
}
}
}
public class sleepcsdn {
public static void main(String[] args) {
A aa=new A();
aa.start();
}
}
运行结果: Thread-0--0正在执行
Thread-0--1正在执行
Thread-0--2正在执行
Thread-0--3正在执行
Thread-0--4正在执行
Thread-0--5正在执行
Thread-0--6正在执行
Thread-0--7正在执行
Thread-0--8正在执行
Thread-0--9正在执行
4、重写的run方法不能抛出异常,原因是重写方法的异常不能大与被重写方法的异常范围。
(七)线程的串行化
1、public final void join(); throw~
class A implements Runnable{
public void run() {
for(int i=0;i<5;i++)
System.out.println(i);
}
}
public class TestJoin {
public static void main(String[] args) {
A aa=new A();
Thread tt=new Thread(aa);
tt.start();
try {
tt.join();//暂停当前正在执行的tt.join();线程,知道t所对应的线程终止之后,当前线程
//才获得继续执行的机会(这里暂停的是主线程)
}
catch(Exception e) {
}
for(int t=5;t<10;t++) {
System.out.println(t);
}
}
}
运行结果:0
1
2
3
4
5
6
7
8
9
(八)Synchronized同步
1、修饰范围:
a、一个方法;
b、一个方法里面的代码块;
2、作用:
a、修饰代码块格式:
synchronized(类对象名 aa){
同步代码块;
}
b、synchronized(类对象名 aa)含义:判断aa是否被其它线程锁定,如果发现aa被其他线程锁定,则当前线程陷入等待,若aa没有被其它线程锁定,则当前线程锁定aa对象,并执行同步代码块,此时其它线程在同步代码块未执行完前都无法执行,待同步代码块执行完后,该线程自动释放aa的锁定,其它线程再次相互竞争对aa的锁定;
c、结果:一个线程在操作某资源时,将不允许其它线程操作该资源,即一次只允许一个线程操作该资源。
d、synchronized修饰一个方法时,实际上时锁定this指针指向的对象;
class A implements Runnable{
public static int tickets=1000;
public void run() {
String str="haha!";
while(tickets>0)synchronized(str) {
System.out.printf("%s已卖出第%d张票\n",Thread.currentThread().getName(),tickets);
--tickets;
}
}
}
public class maipiao {
public static void main(String[] args) {
A aa=new A();
Thread tt1=new Thread(aa);
Thread tt2=new Thread(aa);
tt1.start();
tt2.start();
}
}
(九)生产消费问题
1、aa.wait();
将执行aa.wait的线程转入堵塞状态;
2、aa.notify();
如果所处的线程进入堵塞状态,则将其它陷入堵塞状态的线程其中一个转为就绪状态;
class A{
private char[] date=new char[6];
private int cnt=0;
public synchronized void pust(char a) {
while(cnt==date.length) {
try {
this.wait();
}
catch(Exception e) {
}
}
this.notify();
date[cnt++]=a;
System.out.printf("第%d个生产成功,为:%s\n",cnt,date[cnt-1]);
}
public synchronized char pop() {
char ch;
while(cnt==0) {
try {
this.wait();
}
catch(Exception e) {
}
}
this.notify();
ch=date[cnt-1];
cnt--;
System.out.printf("第%d个消费成功,为:%s\n",cnt+1,ch);
return ch;
}
}
class B implements Runnable{
private A bb=null;
public B(A aa) {
bb=aa;
}
char st;
public void run() {
for(int u =0;u<20;u++) {
st=(char)('a'+u);
bb.pust(st);
}
}
}
class C implements Runnable{
private A cc=null;
public C(A aa) {
cc=aa;
}
public void run() {
for(int u =0;u<20;u++)
cc.pop();
}
}
public class TestSx {
public static void main(String[] args) {
A aa=new A();
B bb=new B(aa);
C cc=new C(aa);
Thread sh=new Thread(bb);
Thread xi=new Thread(cc);
sh.start();
xi.start();
}
}