A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小石姐姐 于 2019-5-17 11:36 编辑

实现多线程方式有两种:
继承Thread类。
实现Runnable接口。
相比继承Thread类,实现Runnable接口的好处:
避免了Java单继承的局限性
适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想
实现多线程方式一:继承Thread类
实现步骤
  • 定义一个类MyThread继承Thread类
  • 在MyThread类中重写run()方法
  • 创建MyThread类的对象
  • 启动线程
    [AppleScript] 纯文本查看 复制代码
    public class MyThread extends Thread {
        @Override
        public void run() {
            for(int i=0; i<100; i++) {
                System.out.println(i);
            }
        }
    }
    public class MyThreadDemo {
        public static void main(String[] args) {
            MyThread my1 = new MyThread();
            MyThread my2 = new MyThread();
    
    //        my1.run();
    //        my2.run();
    
            //void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法
            my1.start();
            my2.start();
        }
    }


run()方法和start()方法的区别?
run():封装线程执行的代码,直接调用,相当于普通方法的调用
start():启动线程;然后由JVM调用此线程的run()方法
线程调度
  • 两种调度方式

    • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
    • 抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些

  • Java使用的是抢占式调度模型
  • 随机性
    假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的

static void sleep(long millis)使当前正在执行的线程停留(暂停执行)指定的毫秒数
void join()等待这个线程死亡
void setDaemon(boolean on)将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
线程的五种状态
  • 新建
  • 就绪
  • 运行
  • 死亡
  • 阻塞

    • 同步方法和同步块

      • synchronized (obj){}
      • 同步方法:synchronized
      • 非静态同步方法的锁:this   静态同步方法的锁是类名.class

    • 同步方法举例

      • StringBuffer和StringBuilder
      • Vector和ArrayList
      • HashTable和HashMap


          • Lock l=new ReentrantLock();    l.lock()   l.unlock();

        • wait(),notify()含义

          • 线程等待:wait()
          • 线程唤醒:notify()
          • public class SellTicket implements Runnable {
                private int tickets = 100;
                private Object obj = new Object();

                @Override
                public void run() {
                    while (true) {
                        //tickets = 100;
                        //t1,t2,t3
                        //假设t1抢到了CPU的执行权
                        //假设t2抢到了CPU的执行权
                        synchronized (obj) {
                            //t1进来后,就会把这段代码给锁起来
                            if (tickets > 0) {
                                try {
                                    Thread.sleep(100);
                                    //t1休息100毫秒
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                //窗口1正在出售第100张票
                                System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                                tickets--; //tickets = 99;
                            }
                        }
                        //t1出来了,这段代码的锁就被释放了
                    }
                }
            }

            public class SellTicketDemo {
                public static void main(String[] args) {
                    SellTicket st = new SellTicket();

                    Thread t1 = new Thread(st, "窗口1");
                    Thread t2 = new Thread(st, "窗口2");
                    Thread t3 = new Thread(st, "窗口3");

                    t1.start();
                    t2.start();
                    t3.start();
                }
            }
          • udp  通信
          • 发送数据
          • [Java] 纯文本查看 复制代码
              //创建发送端的Socket对象(DatagramSocket)
                    // DatagramSocket​() 构造数据报套接字并将其绑定到本地主机上的任何可用端口
                    DatagramSocket ds = new DatagramSocket();
                    //创建数据,并把数据打包
                    //DatagramPacket​(byte[] buf, int length, InetAddress address, int port)
                    //构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
                    byte[] bys = "hello,udp,我来了".getBytes();
            //        int length = bys.length;
            //        InetAddress address = InetAddress.getByName("192.168.1.66");
            //        int port = 10086;
            //        DatagramPacket dp = new DatagramPacket(bys,length,address,port);
                    DatagramPacket dp = new DatagramPacket(bys,bys.length,InetAddress.getByName("192.168.1.104"),10086);
                    //调用DatagramSocket对象的方法发送数据
                    //void send​(DatagramPacket p) 从此套接字发送数据报包
                    ds.send(dp);
            
                    //关闭发送端
                    //void close​() 关闭此数据报套接字
                    ds.close();
          • 接受数据
          • [Java] 纯文本查看 复制代码
            //创建接收端的Socket对象(DatagramSocket)
                    //DatagramSocket​(int port) 构造数据报套接字并将其绑定到本地主机上的指定端口
                    DatagramSocket ds = new DatagramSocket(10086);
            
                    //创建一个数据包,用于接收数据
                    //DatagramPacket​(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包
                    byte[] bys = new byte[1024];
                    DatagramPacket dp = new DatagramPacket(bys,bys.length);
            
                    //调用DatagramSocket对象的方法接收数据
                    System.out.println("启动啦");
                    ds.receive(dp);
                    System.out.println("1111");
            
                    //解析数据包,并把数据在控制台显示
                    //byte[] getData() 返回数据缓冲区
            //        byte[] datas = dp.getData();
                    //int getLength​() 返回要发送的数据的长度或接收到的数据的长度
            //        int len = dp.getLength();
            //        String dataString = new String(datas,0,len);
            //        System.out.println("数据是:" + dataString);
                    System.out.println("数据是:" + new String(dp.getData(),0,dp.getLength()));
            
                    //关闭接收端
                    ds.close();








0 个回复

您需要登录后才可以回帖 登录 | 加入黑马