①Thread类:java中所有有关线程操作的类
// 子线程
public class SonThread extends Thread{
public void run(){
for(int i=0;i<20;i++){
System.err.println("子线程::"+i);
}
}
}
// 测试
public class ThreadTest {
public static void main(String[] args) {
SonThread st=new SonThread();
for (int i = 0; i < 20; i++) {
System.out.println("main::"+i);
}
// 调用重写的run方法,根据调用顺序执行线程操作(单线程按顺序执行)
//st.run();
// 实现多线程操作,通过Thread类对象调用start方法实现,run方法执行
st.start();
for (int i = 0; i < 20; i++) {
System.err.println("main::"+i);
}
}
}
② 实现Runnable接口,重写run方法,需调用Thread类中的start方法开启多线程,并执行指定run方法,避免java中单继承的局限性,和继承带来的类与类之间的耦合度的增加
// 实现类
public class Son implements Runnable{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.err.println("Son::"+i);
}
}
}
// 测试类
public class SonTest {
public static void main(String[] args) {
// 实例化实现Runable的对象
Son s=new Son();
// 与Thread类建立联系
Thread t=new Thread(s);
t.start();
for (int i = 0; i < 500; i++) {
System.out.println("main::"+i);
}
}
}
③ 实现Callable接口可返回结果并且可能抛出异常的任务。可以获得任务执行返回值;通过与Future的结合,可以实现利用Future来跟踪异步计算的结果。
// 实现callable接口
public class TestCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int i = 0;
for (; i < 50; i++) {
System.err.println("call::"+i);
}
return i;
}
}
// 使用
public class Play {
public static void main(String[] args) {
TestCallable tc = new TestCallable();
FutureTask<Integer> ft = new FutureTask<>(tc);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i);
if (i == 20) {
new Thread(ft, "有返回值的线程").start();
}
}
try {
System.out.println("子线程的返回值:" + ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
public Thread()
public Thread(Runnable r)
public void run()
public void start()
public class SonThread extends Thread{
public void run(){
for(int i=0;i<50;i++){
System.err.println(getName()+"::"+i);
}
}
}
public class SonTest {
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread()+"::"+i);
}//Thread[main,5,main]::40
}//格式为:线程名 优先级 线程的执行位置
}
// public static void sleep(long millis)
public class SonThread extends Thread{
public void run(){
for(int i=0;i<50;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(getName()+"::"+i);
}
}
}
public class SonThread extends Thread{
public void run(){
setName("我是线程");
for(int i=0;i<50;i++){
System.err.println(getName()+"::"+i);
}
}
}
// 或者
public class SonTest {
public static void main(String[] args) {
Thread.currentThread().setName("我是线程");
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread()+"::"+i);
}
}
}
public int getPriority()
public class SonTest {
public static void main(String[] args) {
SonThread st=new SonThread();
st.start();
// 设置
st.setPriority(10);
for (int i = 0; i < 50; i++) {
System.err.println(Thread.currentThread()+"::"+i);
}
// 获取
System.out.println(st.getPriority());
}
}
状态 | 权限 |
---|---|
创建状态 | 生存权 |
运行状态 | 既有生存权又有执行权 |
消亡状态 | 既没有生存权也没有执行权 |
临时(阻塞)状态 | 只有生存权没有执行权 |
在于多线程操作是否被开启;创建状态下,没有进行多线程操作;临时状态下的生存权在开启多线程之后,没有获取到执行权
由于实际开发中,并不是所有的类都要继承Thread类,但是只要是java的类就是多线程操作,等待和唤醒的方法是共性的,需要定义在所有类的父类中,因此就把它定义在了Object类中,实际大家更喜欢用sleep来完成多线程操作:到时候自动苏醒
// 测试类
public class Test {
public static void main(String[] args) {
Window w=new Window();
//通过Thread构造器建立连接
// 多线程操作时,多个线程可以同时操作共同资源,当一个线程操作时,其他的线程也有操作的可能
Thread w1=new Thread(w);
Thread w2=new Thread(w);
Thread w3=new Thread(w);
w1.start();
w2.start();
w3.start();
}
}
// 同步代码块版Window
public class Window implements Runnable{
private int tickets=100;
@Override
public void run() {
// 火车站窗口24小时开放
while (true){
// 添加锁,防止超卖问题(3种)
// Object obj=new Object();
// this --本类对象锁
// Window.class --反射机制锁,通过字节码文件获取
synchronized (Window.class){
//同步代码块
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
if(tickets > 0){
System.err.println(Thread.currentThread().getName()+"::"+tickets--);
}
}
}
}
}
// 同步函数版Window
public class Window implements Runnable{
private int tickets=100;
@Override
public void run() {
// 火车站窗口24小时开放
while (true){
fun();
}
}
// 同步函数
private synchronized void fun() {
if(tickets > 0){
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
System.err.println(Thread.currentThread().getName()+"::"+tickets--);
}
}
}
① 同步代码块有3把锁:Object对象锁 this本类对象锁 反射机制锁
② 同步函数有1把锁:this本类对象锁
③ 同步函数只能锁定当前对象(即this),而同步代码块可以锁定任意对象。
④ 同步函数的锁是在方法调用时自动加上的,而同步代码块需要手动指定锁对象。
⑤ 同步函数的锁是在方法调用结束时自动释放的,而同步代码块需要手动释放锁。